libevent(2) : 用libevent改写server端 实现echo_server
2012-11-19 16:57
459 查看
(1) echo_server.c
listen_event的callback函数是 do_accept_cb
bev (buffer event)的三个callback函数:read_cb, write_cb, error_cb。 本例中,server端无需write_cb函数
(2) echo_client.c
一个普通的client端,没有用libevent.
改进方法:可以设置buffer_event, 然后实现write_cb函数和error_cb函数。
3. Makefile.am
AM_CPPFLAGS = -I/usr/local/include
LDADD = -L/usr/local/lib -levent
bin_PROGRAMS = echo-server echo-client
echo_server_SOURCES = echo_server.c
echo_client_SOURCES = echo_client.c
listen_event的callback函数是 do_accept_cb
bev (buffer event)的三个callback函数:read_cb, write_cb, error_cb。 本例中,server端无需write_cb函数
#include <stdio.h> #include <stdlib.h> #include <strings.h> #include <errno.h> #include <assert.h> #include <event2/event.h> #include <event2/bufferevent.h> #define LISTEN_PORT 9999 #define LISTEN_BACKLOG 32 #define oops(msg) { perror(msg); exit(EXIT_FAILURE); } void read_cb(struct bufferevent *bev, void *arg) { #define MAX_LINE 256 char line[MAX_LINE+1]; int n; evutil_socket_t fd = bufferevent_getfd(bev); while (n = bufferevent_read(bev, line, MAX_LINE), n > 0) { line = '\0'; printf("fd=%u, read line: %s\n", fd, line); bufferevent_write(bev, line, n); } } void write_cb(struct bufferevent *bev, void *arg) {} void error_cb(struct bufferevent *bev, short event, void *arg) { evutil_socket_t fd = bufferevent_getfd(bev); printf("fd = %u, ", fd); if (event & BEV_EVENT_TIMEOUT) { printf("Timed out\n"); //if bufferevent_set_timeouts() called } else if (event & BEV_EVENT_EOF) { printf("connection closed\n"); } else if (event & BEV_EVENT_ERROR) { printf("some other error\n"); } bufferevent_free(bev); } void do_accept_cb(evutil_socket_t sockfd, short event_type, void *arg){ evutil_socket_t fd; struct sockaddr_in sin; socklen_t slen; fd = accept(sockfd, (struct sockaddr *)&sin, &slen); if (fd < 0) oops("ERROR: accept: "); if (fd > FD_SETSIZE) oops("ERROR: fd > FD_SETSIZE"); printf("ACCEPT: fd = %u\n", fd); struct event_base *base; base = (struct event_base *)arg; struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); bufferevent_setcb(bev, read_cb, NULL, error_cb, arg); bufferevent_enable(bev, EV_READ|EV_WRITE|EV_PERSIST); } int main(int argc, char **argv){ evutil_socket_t socket_fd; socket_fd = socket(PF_INET, SOCK_STREAM, 0); assert(socket_fd > 0); if(socket_fd == -1) oops("ERROR: socket initiate:"); evutil_make_listen_socket_reuseable(socket_fd); struct sockaddr_in address; bzero((void *)&address, sizeof(address)); address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr("172.16.166.129"); // address.sin_addr.s_addr = 0; address.sin_port = htons(LISTEN_PORT); int bind_return = bind(socket_fd, (struct sockaddr *)&address, sizeof(address)); if(bind_return == -1) oops("ERROR: bind:"); int listen_return = listen(socket_fd, LISTEN_BACKLOG); if(listen_return == -1) oops("ERROR: listen:"); //================================================ puts("Listening..."); evutil_make_socket_nonblocking(socket_fd); struct event_base *base; struct event *listen_event; base = event_base_new(); assert(base != NULL); if(base == NULL) oops("ERROR: event_base_new() :"); listen_event = event_new(base, socket_fd, EV_READ|EV_PERSIST, do_accept_cb, (void*)base); event_add(listen_event, NULL); //NULL: no timeout event_base_dispatch(base); puts("The End."); return 0; }
(2) echo_client.c
一个普通的client端,没有用libevent.
改进方法:可以设置buffer_event, 然后实现write_cb函数和error_cb函数。
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include <arpa/inet.h> #define oops(msg) { perror(msg); exit(EXIT_FAILURE); } #define SIZE 256 #define LISTEN_PORT 9999 int main(){ int socket_fd = socket(PF_INET, SOCK_STREAM, 0); if(socket_fd == -1) oops("socket initiating error..."); struct sockaddr_in address; bzero(&address, sizeof(address)); address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr("172.16.166.129"); // address.sin_addr.s_addr = 0; address.sin_port = htons(LISTEN_PORT); int connect_result = connect(socket_fd, (struct sockaddr*)&address, sizeof(address)); if(connect_result == -1) oops("connect error..."); char buffer[] = "hello world"; ssize_t write_length = write(socket_fd, buffer, strlen(buffer)+1); //write to socket_fd if(write_length != (strlen(buffer)+1)) oops("error: write ..."); ssize_t read_length = read(socket_fd, buffer, strlen(buffer)+1); if(read_length == -1) oops("error: read data from socket..."); printf("the ret msg is: %s\n", buffer); close(socket_fd); return EXIT_SUCCESS; }
3. Makefile.am
AM_CPPFLAGS = -I/usr/local/include
LDADD = -L/usr/local/lib -levent
bin_PROGRAMS = echo-server echo-client
echo_server_SOURCES = echo_server.c
echo_client_SOURCES = echo_client.c
相关文章推荐
- 完成端口实现echo tcp server
- Asio实现的实用echo server
- C++05:使用ACE-用ACE实现简易Echo Server
- libevent入门教程:Echo Server based on libevent
- C++03:使用Boost-用Asio实现简易Echo Server
- 采用epoll实现echo server和client
- 使用libevent:echo server
- 使用Boost-用Asio实现简易Echo Server
- libevent入门教程:Echo Server based on libevent
- 【转载】libevent入门教程:Echo Server based on libevent
- python实现-恒定数量进程池的echo server模型 基于multiprocessing
- Libevent:Echo Server Based on libevent
- 基于ACE reactor_echo_server实现
- Linux网络编程之echo server的实现
- [转载]libevent入门教程:Echo Server based on libevent
- c10k测试:使用asio实现多线程回显服务器(echo server)_Runyon_新浪博客
- libevent入门教程:Echo Server based on libevent
- 采用epoll实现echo server和client
- C++03:使用Boost-用Asio实现简易Echo Server
- libevent入门教程:Echo Server based on libevent