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

2023-11-16


转载请注明出处:http://blog.csdn.net/luotuo44/article/details/39670221



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

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

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

        


初等:

客户端代码:

[cpp]   view plain  copy   在CODE上查看代码片 派生到我的代码片
  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   在CODE上查看代码片 派生到我的代码片
  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   在CODE上查看代码片 派生到我的代码片
  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   在CODE上查看代码片 派生到我的代码片
  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   在CODE上查看代码片 派生到我的代码片
  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   在CODE上查看代码片 派生到我的代码片
  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. }    







本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Libevent使用例子,从简单到复杂 的相关文章

  • Ubuntu配置apt-get install自动补全功能

    1 执行以下命令 sudo apt get update sudo apt get upgrade 2 默认会安装bash completion 如果没有安装 请执行以下命令 sudo apt get install bash comple
  • JAVA实现文件的上传和下载

    目录 一 文件的上传和下载的作用 什么是文件上传 文件的下载及需求 为什么使用文件上传 二 文件上传 文件上传的关键 不同的框架提供了不同的获取输入流的方式 Servlet上传案例 文件上传细节 存储位置 文件上传问题 目录分离 三 文件下
  • 前端react框架的部分总结

    前端react框架的部分总结 react的优势 react相对其他框架优势 高性能高效率 实现了前端界面的高性能高效率开发 所以说react很擅长处理组件化的页面 和vue的区别 在React中 一切都是JavaScript 所有的组件的渲
  • Android APP应用启动页白屏(StartingWindow)优化

    转自 https www cnblogs com whycxb p 9312914 html 本人采用这种方法没有效果 启动图片出来第一帧 我应用的第一帧也出来了 启动背景颜色没有调试出来 Theme AppCompat Light Dar
  • Java基础-一些容易被人忽视却重要的Java基础知识(二)

    文章目录 一 重载和重写 1 重载 2 重写 一 重载和重写 1 重载 被重载的方法必须改变参数列表 参数个数或者类型 顺序不一样 被重载的方法可以改变返回类型 被重载的方法可以改变访问修饰符 可以使用新的或更广的检查异常 方法能够在同一类
  • java动态生成pdf文件的方法

    java动态生成pdf文件 文章目录 java动态生成pdf文件 前言 一 生成pdf模板 二 使用步骤 1 使用jar包 2 pdf实现方法 总结 前言 java开发过程中难免会遇到生成文件的需求 这里简单介绍一下关于pdf格式的文件的动
  • python常见的面试题,看你都掌握了吗

    前言 Python是目前编程领域最受欢迎的语言 在本文中 我将总结Python面试中最常见的50个问题 每道题都提供参考答案 希望能够帮助你在2019年求职面试中脱颖而出 找到一份高薪工作 这些面试题涉及Python基础知识 Python编
  • usb转网口转换器经常自动断网

    问题 最近使用一个usb转网口的扩展坞 发现和其它机器通信时 经常会自动断网 原因 和设备的电源管理策略有关 USB设备的 允许计算机自动关闭此设备以节约电源 选项默认是选中的 而网络设备的此选项默认值是未选中 解决办法 打开设备管理器 找
  • MATLAB基本语法详解

    MATLAB基本语法详解 下面内容 变量 M Files 决策 循环容易掌握 命令 数据类型 运算符不需要记住 用了再查 变量 每个MatLab变量可以是数组或者矩阵 最简单的方法指定变量 x 3 定义并初始化 赋值 变量x MATLAB上
  • 搭建redis主从服务 :master_link_status:down 主从无法连接问题汇总

    1 问题描述 主从无法连接问题 2 搭建 https blog csdn net ling811 article details 53637257 https blog csdn net qq 24113267 article detail
  • 双机热备 ip地址_SBC双机热备方案

    概述 随着通信全IP化的进程 现代企业中基于IP的语音 视频 会议 融合通信已广泛应用 同时企业通信也面临着新挑战 包括安全攻击 跨网NAT穿越以及业务稳定运行 高可靠方案尤为重要 因此在组网中部署SBC Session Border Co
  • NPN和PNP三极管原理以及应用电路设计

    一 基本概念与原理 三极管最主要的功能是电流放大 模拟电路 和开关作用 数字电路 常用的三极管有 S9014 S8550等型号 三极管由两个PN结构成 共用的一个电极成为三极管的基极 用字母b表示 其他的两个电极成为集电极 用字母c表示 和
  • 安卓加固基础(二)

    4 反调试 4 1 思路一 一个进程最多只能被一个进程ptrace 本文章主要针对安卓so反调试和最初的加壳方法进行了一下总结 在处于调试状态时 Linux会向 proc pid status写入一些进程状态信息 比如TracerPid字段
  • 【leetcode 力扣刷题】删除字符串中的子串or字符以满足要求

    删除字符串中的子串或者字符以满足题意要求 1234 替换子串得到平衡字符串 680 验证回文串 917 仅仅反转字母 1234 替换子串得到平衡字符串 题目链接 1234 替换子串得到平衡字符串 题目内容 题目中给出了平衡字符串的定义 只有

随机推荐