首页 > 代码库 > [z]Libevent使用例子,从简单到复杂

[z]Libevent使用例子,从简单到复杂

[z]http://blog.csdn.net/luotuo44/article/details/39670221

 

        本文从简单到复杂,展示如何使用libevent。网上的许多例子都是只有服务器端的,本文里面客户端和服务器端都有,以飨读者。

        关于libevent编程时的一些疑问可以阅读《libevent编程疑难解答》。假如读者还想了解libevent的具体实现,可以阅读《libevent源码分析》系统文章。

        不说这么多了,直接上代码。

        

 

初等:

客户端代码:

 

[cpp] view plain copy
 
 技术分享技术分享
  1. #include<sys/types.h>  
  2. #include<sys/socket.h>  
  3. #include<netinet/in.h>  
  4. #include<arpa/inet.h>  
  5. #include<errno.h>  
  6. #include<unistd.h>  
  7.   
  8. #include<stdio.h>  
  9. #include<string.h>  
  10. #include<stdlib.h>  
  11.   
  12. #include<event.h>  
  13. #include<event2/util.h>  
  14.   
  15.   
  16.   
  17.   
  18. int tcp_connect_server(const char* server_ip, int port);  
  19.   
  20.   
  21. void cmd_msg_cb(int fd, short events, void* arg);  
  22. void socket_read_cb(int fd, short events, void *arg);  
  23.   
  24. int main(int argc, char** argv)  
  25. {  
  26.     if( argc < 3 )  
  27.     {  
  28.         printf("please input 2 parameter\n");  
  29.         return -1;  
  30.     }  
  31.   
  32.   
  33.     //两个参数依次是服务器端的IP地址、端口号  
  34.     int sockfd = tcp_connect_server(argv[1], atoi(argv[2]));  
  35.     if( sockfd == -1)  
  36.     {  
  37.         perror("tcp_connect error ");  
  38.         return -1;  
  39.     }  
  40.   
  41.     printf("connect to server successful\n");  
  42.   
  43.     struct event_base* base = event_base_new();  
  44.   
  45.     struct event *ev_sockfd = event_new(base, sockfd,  
  46.                                         EV_READ | EV_PERSIST,  
  47.                                         socket_read_cb, NULL);  
  48.     event_add(ev_sockfd, NULL);  
  49.   
  50.     //监听终端输入事件  
  51.     struct event* ev_cmd = event_new(base, STDIN_FILENO,  
  52.                                       EV_READ | EV_PERSIST, cmd_msg_cb,  
  53.                                       (void*)&sockfd);  
  54.   
  55.   
  56.     event_add(ev_cmd, NULL);  
  57.   
  58.     event_base_dispatch(base);  
  59.   
  60.     printf("finished \n");  
  61.     return 0;  
  62. }  
  63.   
  64.   
  65.   
  66.   
  67.   
  68.   
  69. void cmd_msg_cb(int fd, short events, void* arg)  
  70. {  
  71.     char msg[1024];  
  72.   
  73.     int ret = read(fd, msg, sizeof(msg));  
  74.     if( ret <= 0 )  
  75.     {  
  76.         perror("read fail ");  
  77.         exit(1);  
  78.     }  
  79.   
  80.     int sockfd = *((int*)arg);  
  81.   
  82.     //把终端的消息发送给服务器端  
  83.     //为了简单起见,不考虑写一半数据的情况  
  84.     write(sockfd, msg, ret);  
  85. }  
  86.   
  87.   
  88. void socket_read_cb(int fd, short events, void *arg)  
  89. {  
  90.     char msg[1024];  
  91.   
  92.     //为了简单起见,不考虑读一半数据的情况  
  93.     int len = read(fd, msg, sizeof(msg)-1);  
  94.     if( len <= 0 )  
  95.     {  
  96.         perror("read fail ");  
  97.         exit(1);  
  98.     }  
  99.   
  100.     msg[len] = ‘\0‘;  
  101.   
  102.     printf("recv %s from server\n", msg);  
  103. }  
  104.   
  105.   
  106.   
  107. typedef struct sockaddr SA;  
  108. int tcp_connect_server(const char* server_ip, int port)  
  109. {  
  110.     int sockfd, status, save_errno;  
  111.     struct sockaddr_in server_addr;  
  112.   
  113.     memset(&server_addr, 0, sizeof(server_addr) );  
  114.   
  115.     server_addr.sin_family = AF_INET;  
  116.     server_addr.sin_port = htons(port);  
  117.     status = inet_aton(server_ip, &server_addr.sin_addr);  
  118.   
  119.     if( status == 0 ) //the server_ip is not valid value  
  120.     {  
  121.         errno = EINVAL;  
  122.         return -1;  
  123.     }  
  124.   
  125.     sockfd = ::socket(PF_INET, SOCK_STREAM, 0);  
  126.     if( sockfd == -1 )  
  127.         return sockfd;  
  128.   
  129.   
  130.     status = ::connect(sockfd, (SA*)&server_addr, sizeof(server_addr) );  
  131.   
  132.     if( status == -1 )  
  133.     {  
  134.         save_errno = errno;  
  135.         ::close(sockfd);  
  136.         errno = save_errno; //the close may be error  
  137.         return -1;  
  138.     }  
  139.   
  140.     evutil_make_socket_nonblocking(sockfd);  
  141.   
  142.     return sockfd;  
  143. }  

 

 

 

服务器端代码:

 

[cpp] view plain copy
 
 技术分享技术分享
  1. #include<stdio.h>  
  2. #include<string.h>  
  3. #include<errno.h>  
  4.   
  5. #include<unistd.h>  
  6. #include<event.h>  
  7.   
  8.   
  9.   
  10. void accept_cb(int fd, short events, void* arg);  
  11. void socket_read_cb(int fd, short events, void *arg);  
  12.   
  13. int tcp_server_init(int port, int listen_num);  
  14.   
  15. int main(int argc, char** argv)  
  16. {  
  17.   
  18.     int listener = tcp_server_init(9999, 10);  
  19.     if( listener == -1 )  
  20.     {  
  21.         perror(" tcp_server_init error ");  
  22.         return -1;  
  23.     }  
  24.   
  25.     struct event_base* base = event_base_new();  
  26.   
  27.     //添加监听客户端请求连接事件  
  28.     struct event* ev_listen = event_new(base, listener, EV_READ | EV_PERSIST,  
  29.                                         accept_cb, base);  
  30.     event_add(ev_listen, NULL);  
  31.   
  32.   
  33.     event_base_dispatch(base);  
  34.   
  35.     return 0;  
  36. }  
  37.   
  38.   
  39.   
  40. void accept_cb(int fd, short events, void* arg)  
  41. {  
  42.     evutil_socket_t sockfd;  
  43.   
  44.     struct sockaddr_in client;  
  45.     socklen_t len = sizeof(client);  
  46.   
  47.     sockfd = ::accept(fd, (struct sockaddr*)&client, &len );  
  48.     evutil_make_socket_nonblocking(sockfd);  
  49.   
  50.     printf("accept a client %d\n", sockfd);  
  51.   
  52.     struct event_base* base = (event_base*)arg;  
  53.   
  54.     //仅仅是为了动态创建一个event结构体  
  55.     struct event *ev = event_new(NULL, -1, 0, NULL, NULL);  
  56.     //将动态创建的结构体作为event的回调参数  
  57.     event_assign(ev, base, sockfd, EV_READ | EV_PERSIST,  
  58.                  socket_read_cb, (void*)ev);  
  59.   
  60.     event_add(ev, NULL);  
  61. }  
  62.   
  63.   
  64. void socket_read_cb(int fd, short events, void *arg)  
  65. {  
  66.     char msg[4096];  
  67.     struct event *ev = (struct event*)arg;  
  68.     int len = read(fd, msg, sizeof(msg) - 1);  
  69.   
  70.   
  71.   
  72.     if( len <= 0 )  
  73.     {  
  74.         printf("some error happen when read\n");  
  75.         event_free(ev);  
  76.         close(fd);  
  77.         return ;  
  78.     }  
  79.   
  80.     msg[len] = ‘\0‘;  
  81.     printf("recv the client msg: %s", msg);  
  82.   
  83.     char reply_msg[4096] = "I have recvieced the msg: ";  
  84.     strcat(reply_msg + strlen(reply_msg), msg);  
  85.   
  86.     write(fd, reply_msg, strlen(reply_msg) );  
  87. }  
  88.   
  89.   
  90.   
  91. typedef struct sockaddr SA;  
  92. int tcp_server_init(int port, int listen_num)  
  93. {  
  94.     int errno_save;  
  95.     evutil_socket_t listener;  
  96.   
  97.     listener = ::socket(AF_INET, SOCK_STREAM, 0);  
  98.     if( listener == -1 )  
  99.         return -1;  
  100.   
  101.     //允许多次绑定同一个地址。要用在socket和bind之间  
  102.     evutil_make_listen_socket_reuseable(listener);  
  103.   
  104.     struct sockaddr_in sin;  
  105.     sin.sin_family = AF_INET;  
  106.     sin.sin_addr.s_addr = 0;  
  107.     sin.sin_port = htons(port);  
  108.   
  109.     if( ::bind(listener, (SA*)&sin, sizeof(sin)) < 0 )  
  110.         goto error;  
  111.   
  112.     if( ::listen(listener, listen_num) < 0)  
  113.         goto error;  
  114.   
  115.   
  116.     //跨平台统一接口,将套接字设置为非阻塞状态  
  117.     evutil_make_socket_nonblocking(listener);  
  118.   
  119.     return listener;  
  120.   
  121.     error:  
  122.         errno_save = errno;  
  123.         evutil_closesocket(listener);  
  124.         errno = errno_save;  
  125.   
  126.         return -1;  
  127. }  

 

 

 

 

 

中等:

客户端代码:

 

[cpp] view plain copy
 
 技术分享技术分享
  1. #include<sys/types.h>  
  2. #include<sys/socket.h>  
  3. #include<netinet/in.h>  
  4. #include<arpa/inet.h>  
  5. #include<errno.h>  
  6. #include<unistd.h>  
  7.   
  8. #include<stdio.h>  
  9. #include<string.h>  
  10. #include<stdlib.h>  
  11.   
  12. #include<event.h>  
  13. #include<event2/bufferevent.h>  
  14. #include<event2/buffer.h>  
  15. #include<event2/util.h>  
  16.   
  17.   
  18.   
  19.   
  20. int tcp_connect_server(const char* server_ip, int port);  
  21.   
  22.   
  23. void cmd_msg_cb(int fd, short events, void* arg);  
  24. void server_msg_cb(struct bufferevent* bev, void* arg);  
  25. void event_cb(struct bufferevent *bev, short event, void *arg);  
  26.   
  27. int main(int argc, char** argv)  
  28. {  
  29.     if( argc < 3 )  
  30.     {  
  31.         printf("please input 2 parameter\n");  
  32.         return -1;  
  33.     }  
  34.   
  35.   
  36.     //两个参数依次是服务器端的IP地址、端口号  
  37.     int sockfd = tcp_connect_server(argv[1], atoi(argv[2]));  
  38.     if( sockfd == -1)  
  39.     {  
  40.         perror("tcp_connect error ");  
  41.         return -1;  
  42.     }  
  43.   
  44.     printf("connect to server successful\n");  
  45.   
  46.     struct event_base* base = event_base_new();  
  47.   
  48.     struct bufferevent* bev = bufferevent_socket_new(base, sockfd,  
  49.                                                      BEV_OPT_CLOSE_ON_FREE);  
  50.   
  51.     //监听终端输入事件  
  52.     struct event* ev_cmd = event_new(base, STDIN_FILENO,  
  53.                                       EV_READ | EV_PERSIST, cmd_msg_cb,  
  54.                                       (void*)bev);  
  55.     event_add(ev_cmd, NULL);  
  56.   
  57.     //当socket关闭时会用到回调参数  
  58.     bufferevent_setcb(bev, server_msg_cb, NULL, event_cb, (void*)ev_cmd);  
  59.     bufferevent_enable(bev, EV_READ | EV_PERSIST);  
  60.   
  61.   
  62.     event_base_dispatch(base);  
  63.   
  64.     printf("finished \n");  
  65.     return 0;  
  66. }  
  67.   
  68.   
  69.   
  70.   
  71.   
  72.   
  73. void cmd_msg_cb(int fd, short events, void* arg)  
  74. {  
  75.     char msg[1024];  
  76.   
  77.     int ret = read(fd, msg, sizeof(msg));  
  78.     if( ret < 0 )  
  79.     {  
  80.         perror("read fail ");  
  81.         exit(1);  
  82.     }  
  83.   
  84.     struct bufferevent* bev = (struct bufferevent*)arg;  
  85.   
  86.     //把终端的消息发送给服务器端  
  87.     bufferevent_write(bev, msg, ret);  
  88. }  
  89.   
  90.   
  91. void server_msg_cb(struct bufferevent* bev, void* arg)  
  92. {  
  93.     char msg[1024];  
  94.   
  95.     size_t len = bufferevent_read(bev, msg, sizeof(msg));  
  96.     msg[len] = ‘\0‘;  
  97.   
  98.     printf("recv %s from server\n", msg);  
  99. }  
  100.   
  101.   
  102. void event_cb(struct bufferevent *bev, short event, void *arg)  
  103. {  
  104.   
  105.     if (event & BEV_EVENT_EOF)  
  106.         printf("connection closed\n");  
  107.     else if (event & BEV_EVENT_ERROR)  
  108.         printf("some other error\n");  
  109.   
  110.     //这将自动close套接字和free读写缓冲区  
  111.     bufferevent_free(bev);  
  112.   
  113.     struct event *ev = (struct event*)arg;  
  114.     //因为socket已经没有,所以这个event也没有存在的必要了  
  115.     event_free(ev);  
  116. }  
  117.   
  118.   
  119. typedef struct sockaddr SA;  
  120. int tcp_connect_server(const char* server_ip, int port)  
  121. {  
  122.     int sockfd, status, save_errno;  
  123.     struct sockaddr_in server_addr;  
  124.   
  125.     memset(&server_addr, 0, sizeof(server_addr) );  
  126.   
  127.     server_addr.sin_family = AF_INET;  
  128.     server_addr.sin_port = htons(port);  
  129.     status = inet_aton(server_ip, &server_addr.sin_addr);  
  130.   
  131.     if( status == 0 ) //the server_ip is not valid value  
  132.     {  
  133.         errno = EINVAL;  
  134.         return -1;  
  135.     }  
  136.   
  137.     sockfd = ::socket(PF_INET, SOCK_STREAM, 0);  
  138.     if( sockfd == -1 )  
  139.         return sockfd;  
  140.   
  141.   
  142.     status = ::connect(sockfd, (SA*)&server_addr, sizeof(server_addr) );  
  143.   
  144.     if( status == -1 )  
  145.     {  
  146.         save_errno = errno;  
  147.         ::close(sockfd);  
  148.         errno = save_errno; //the close may be error  
  149.         return -1;  
  150.     }  
  151.   
  152.     evutil_make_socket_nonblocking(sockfd);  
  153.   
  154.     return sockfd;  
  155. }  

 

 

 

 

服务器端代码:

 

[cpp] view plain copy
 
 技术分享技术分享
  1. #include<stdio.h>  
  2. #include<string.h>  
  3. #include<errno.h>  
  4.   
  5. #include<event.h>  
  6. #include<event2/bufferevent.h>  
  7.   
  8.   
  9.   
  10. void accept_cb(int fd, short events, void* arg);  
  11. void socket_read_cb(bufferevent* bev, void* arg);  
  12. void event_cb(struct bufferevent *bev, short event, void *arg);  
  13. int tcp_server_init(int port, int listen_num);  
  14.   
  15. int main(int argc, char** argv)  
  16. {  
  17.   
  18.     int listener = tcp_server_init(9999, 10);  
  19.     if( listener == -1 )  
  20.     {  
  21.         perror(" tcp_server_init error ");  
  22.         return -1;  
  23.     }  
  24.   
  25.     struct event_base* base = event_base_new();  
  26.   
  27.     //添加监听客户端请求连接事件  
  28.     struct event* ev_listen = event_new(base, listener, EV_READ | EV_PERSIST,  
  29.                                         accept_cb, base);  
  30.     event_add(ev_listen, NULL);  
  31.   
  32.   
  33.     event_base_dispatch(base);  
  34.     event_base_free(base);  
  35.   
  36.   
  37.     return 0;  
  38. }  
  39.   
  40.   
  41.   
  42. void accept_cb(int fd, short events, void* arg)  
  43. {  
  44.     evutil_socket_t sockfd;  
  45.   
  46.     struct sockaddr_in client;  
  47.     socklen_t len = sizeof(client);  
  48.   
  49.     sockfd = ::accept(fd, (struct sockaddr*)&client, &len );  
  50.     evutil_make_socket_nonblocking(sockfd);  
  51.   
  52.     printf("accept a client %d\n", sockfd);  
  53.   
  54.     struct event_base* base = (event_base*)arg;  
  55.   
  56.     bufferevent* bev = bufferevent_socket_new(base, sockfd, BEV_OPT_CLOSE_ON_FREE);  
  57.     bufferevent_setcb(bev, socket_read_cb, NULL, event_cb, arg);  
  58.   
  59.     bufferevent_enable(bev, EV_READ | EV_PERSIST);  
  60. }  
  61.   
  62.   
  63.   
  64. void socket_read_cb(bufferevent* bev, void* arg)  
  65. {  
  66.     char msg[4096];  
  67.   
  68.     size_t len = bufferevent_read(bev, msg, sizeof(msg));  
  69.   
  70.     msg[len] = ‘\0‘;  
  71.     printf("recv the client msg: %s", msg);  
  72.   
  73.   
  74.     char reply_msg[4096] = "I have recvieced the msg: ";  
  75.   
  76.     strcat(reply_msg + strlen(reply_msg), msg);  
  77.     bufferevent_write(bev, reply_msg, strlen(reply_msg));  
  78. }  
  79.   
  80.   
  81.   
  82. void event_cb(struct bufferevent *bev, short event, void *arg)  
  83. {  
  84.   
  85.     if (event & BEV_EVENT_EOF)  
  86.         printf("connection closed\n");  
  87.     else if (event & BEV_EVENT_ERROR)  
  88.         printf("some other error\n");  
  89.   
  90.     //这将自动close套接字和free读写缓冲区  
  91.     bufferevent_free(bev);  
  92. }  
  93.   
  94.   
  95. typedef struct sockaddr SA;  
  96. int tcp_server_init(int port, int listen_num)  
  97. {  
  98.     int errno_save;  
  99.     evutil_socket_t listener;  
  100.   
  101.     listener = ::socket(AF_INET, SOCK_STREAM, 0);  
  102.     if( listener == -1 )  
  103.         return -1;  
  104.   
  105.     //允许多次绑定同一个地址。要用在socket和bind之间  
  106.     evutil_make_listen_socket_reuseable(listener);  
  107.   
  108.     struct sockaddr_in sin;  
  109.     sin.sin_family = AF_INET;  
  110.     sin.sin_addr.s_addr = 0;  
  111.     sin.sin_port = htons(port);  
  112.   
  113.     if( ::bind(listener, (SA*)&sin, sizeof(sin)) < 0 )  
  114.         goto error;  
  115.   
  116.     if( ::listen(listener, listen_num) < 0)  
  117.         goto error;  
  118.   
  119.   
  120.     //跨平台统一接口,将套接字设置为非阻塞状态  
  121.     evutil_make_socket_nonblocking(listener);  
  122.   
  123.     return listener;  
  124.   
  125.     error:  
  126.         errno_save = errno;  
  127.         evutil_closesocket(listener);  
  128.         errno = errno_save;  
  129.   
  130.         return -1;  
  131. }  



 

 

高等:

客户端代码:

 

[cpp] view plain copy
 
 技术分享技术分享
  1. #include<sys/types.h>  
  2. #include<sys/socket.h>  
  3. #include<netinet/in.h>  
  4. #include<arpa/inet.h>  
  5. #include<errno.h>  
  6. #include<unistd.h>  
  7.   
  8. #include<stdio.h>  
  9. #include<string.h>  
  10. #include<stdlib.h>  
  11.   
  12. #include<event.h>  
  13. #include<event2/bufferevent.h>  
  14. #include<event2/buffer.h>  
  15. #include<event2/util.h>  
  16.   
  17.   
  18.   
  19.   
  20. int tcp_connect_server(const char* server_ip, int port);  
  21.   
  22.   
  23. void cmd_msg_cb(int fd, short events, void* arg);  
  24. void server_msg_cb(struct bufferevent* bev, void* arg);  
  25. void event_cb(struct bufferevent *bev, short event, void *arg);  
  26.   
  27. int main(int argc, char** argv)  
  28. {  
  29.     if( argc < 3 )  
  30.     {  
  31.         //两个参数依次是服务器端的IP地址、端口号  
  32.         printf("please input 2 parameter\n");  
  33.         return -1;  
  34.     }  
  35.   
  36.     struct event_base *base = event_base_new();  
  37.   
  38.     struct bufferevent* bev = bufferevent_socket_new(base, -1,  
  39.                                                      BEV_OPT_CLOSE_ON_FREE);  
  40.   
  41.     //监听终端输入事件  
  42.     struct event* ev_cmd = event_new(base, STDIN_FILENO,  
  43.                                      EV_READ | EV_PERSIST,  
  44.                                      cmd_msg_cb, (void*)bev);  
  45.   
  46.   
  47.     event_add(ev_cmd, NULL);  
  48.   
  49.     struct sockaddr_in server_addr;  
  50.   
  51.     memset(&server_addr, 0, sizeof(server_addr) );  
  52.   
  53.     server_addr.sin_family = AF_INET;  
  54.     server_addr.sin_port = htons(atoi(argv[2]));  
  55.     inet_aton(argv[1], &server_addr.sin_addr);  
  56.   
  57.     bufferevent_socket_connect(bev, (struct sockaddr *)&server_addr,  
  58.                                sizeof(server_addr));  
  59.   
  60.   
  61.     bufferevent_setcb(bev, server_msg_cb, NULL, event_cb, (void*)ev_cmd);  
  62.     bufferevent_enable(bev, EV_READ | EV_PERSIST);  
  63.   
  64.   
  65.   
  66.     event_base_dispatch(base);  
  67.   
  68.     printf("finished \n");  
  69.     return 0;  
  70. }  
  71.   
  72.   
  73.   
  74.   
  75.   
  76. void cmd_msg_cb(int fd, short events, void* arg)  
  77. {  
  78.     char msg[1024];  
  79.   
  80.     int ret = read(fd, msg, sizeof(msg));  
  81.     if( ret < 0 )  
  82.     {  
  83.         perror("read fail ");  
  84.         exit(1);  
  85.     }  
  86.   
  87.     struct bufferevent* bev = (struct bufferevent*)arg;  
  88.   
  89.     //把终端的消息发送给服务器端  
  90.     bufferevent_write(bev, msg, ret);  
  91. }  
  92.   
  93.   
  94. void server_msg_cb(struct bufferevent* bev, void* arg)  
  95. {  
  96.     char msg[1024];  
  97.   
  98.     size_t len = bufferevent_read(bev, msg, sizeof(msg));  
  99.     msg[len] = ‘\0‘;  
  100.   
  101.     printf("recv %s from server\n", msg);  
  102. }  
  103.   
  104.   
  105. void event_cb(struct bufferevent *bev, short event, void *arg)  
  106. {  
  107.   
  108.     if (event & BEV_EVENT_EOF)  
  109.         printf("connection closed\n");  
  110.     else if (event & BEV_EVENT_ERROR)  
  111.         printf("some other error\n");  
  112.     else if( event & BEV_EVENT_CONNECTED)  
  113.     {  
  114.         printf("the client has connected to server\n");  
  115.         return ;  
  116.     }  
  117.   
  118.     //这将自动close套接字和free读写缓冲区  
  119.     bufferevent_free(bev);  
  120.   
  121.     struct event *ev = (struct event*)arg;  
  122.     event_free(ev);  
  123. }  



 

 

服务器端代码:

 

[cpp] view plain copy
 
 技术分享技术分享
    1. #include<netinet/in.h>    
    2. #include<sys/socket.h>    
    3. #include<unistd.h>    
    4.     
    5. #include<stdio.h>    
    6. #include<string.h>    
    7.     
    8. #include<event.h>    
    9. #include<listener.h>    
    10. #include<bufferevent.h>    
    11. #include<thread.h>    
    12.     
    13.     
    14. void listener_cb(evconnlistener *listener, evutil_socket_t fd,    
    15.                  struct sockaddr *sock, int socklen, void *arg);    
    16.     
    17. void socket_read_cb(bufferevent *bev, void *arg);    
    18. void socket_event_cb(bufferevent *bev, short events, void *arg);    
    19.     
    20. int main()    
    21. {    
    22.     //evthread_use_pthreads();//enable threads    
    23.     
    24.     struct sockaddr_in sin;    
    25.     memset(&sin, 0, sizeof(struct sockaddr_in));    
    26.     sin.sin_family = AF_INET;    
    27.     sin.sin_port = htons(9999);    
    28.     
    29.     event_base *base = event_base_new();    
    30.     evconnlistener *listener    
    31.             = evconnlistener_new_bind(base, listener_cb, base,    
    32.                                       LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE,    
    33.                                       10, (struct sockaddr*)&sin,    
    34.                                       sizeof(struct sockaddr_in));    
    35.     
    36.     event_base_dispatch(base);    
    37.     
    38.     evconnlistener_free(listener);    
    39.     event_base_free(base);    
    40.     
    41.     return 0;    
    42. }    
    43.     
    44.     
    45. //一个新客户端连接上服务器了    
    46. //当此函数被调用时,libevent已经帮我们accept了这个客户端。该客户端的  
    47. //文件描述符为fd  
    48. void listener_cb(evconnlistener *listener, evutil_socket_t fd,    
    49.                  struct sockaddr *sock, int socklen, void *arg)    
    50. {    
    51.     printf("accept a client %d\n", fd);    
    52.     
    53.     event_base *base = (event_base*)arg;    
    54.     
    55.     //为这个客户端分配一个bufferevent    
    56.     bufferevent *bev =  bufferevent_socket_new(base, fd,    
    57.                                                BEV_OPT_CLOSE_ON_FREE);    
    58.     
    59.     bufferevent_setcb(bev, socket_read_cb, NULL, socket_event_cb, NULL);    
    60.     bufferevent_enable(bev, EV_READ | EV_PERSIST);    
    61. }    
    62.     
    63.     
    64. void socket_read_cb(bufferevent *bev, void *arg)    
    65. {    
    66.     char msg[4096];    
    67.     
    68.     size_t len = bufferevent_read(bev, msg, sizeof(msg)-1 );    
    69.     
    70.     msg[len] = ‘\0‘;    
    71.     printf("server read the data %s\n", msg);    
    72.     
    73.     char reply[] = "I has read your data";    
    74.     bufferevent_write(bev, reply, strlen(reply) );    
    75. }    
    76.     
    77.     
    78. void socket_event_cb(bufferevent *bev, short events, void *arg)    
    79. {    
    80.     if (events & BEV_EVENT_EOF)    
    81.         printf("connection closed\n");    
    82.     else if (events & BEV_EVENT_ERROR)    
    83.         printf("some other error\n");    
    84.     
    85.     //这将自动close套接字和free读写缓冲区    
    86.     bufferevent_free(bev);    
    87. }    

[z]Libevent使用例子,从简单到复杂