日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2024/4/14 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Libevent使用例子,从简单到复杂 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?? ? ??本文從簡單到復雜,展示如何使用libevent。網上的許多例子都是只有服務器端的,本文里面客戶端和服務器端都有,以饗讀者。

? ? ? ??關于libevent編程時的一些疑問可以閱讀《libevent編程疑難解答》。假如讀者還想了解libevent的具體實現,可以閱讀《libevent源碼分析》系統文章。

? ? ? ??不說這么多了,直接上代碼。

? ? ? ??

?

初等:

客戶端代碼:

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 }

服務器端代碼:

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 }

中等:

客戶端代碼:

#include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<errno.h> #include<unistd.h>#include<stdio.h> #include<string.h> #include<stdlib.h>#include<event.h> #include<event2/bufferevent.h> #include<event2/buffer.h> #include<event2/util.h>int tcp_connect_server(const char* server_ip, int port);void cmd_msg_cb(int fd, short events, void* arg); void server_msg_cb(struct bufferevent* bev, void* arg); void event_cb(struct bufferevent *bev, short event, void *arg);int main(int argc, char** argv) {if( argc < 3 ){printf("please input 2 parameter\n");return -1;}//兩個參數依次是服務器端的IP地址、端口號int sockfd = tcp_connect_server(argv[1], atoi(argv[2]));if( sockfd == -1){perror("tcp_connect error ");return -1;}printf("connect to server successful\n");struct event_base* base = event_base_new();struct bufferevent* bev = bufferevent_socket_new(base, sockfd,BEV_OPT_CLOSE_ON_FREE);//監聽終端輸入事件struct event* ev_cmd = event_new(base, STDIN_FILENO,EV_READ | EV_PERSIST, cmd_msg_cb,(void*)bev);event_add(ev_cmd, NULL);//當socket關閉時會用到回調參數bufferevent_setcb(bev, server_msg_cb, NULL, event_cb, (void*)ev_cmd);bufferevent_enable(bev, EV_READ | EV_PERSIST);event_base_dispatch(base);printf("finished \n");return 0; }void cmd_msg_cb(int fd, short events, void* arg) {char msg[1024];int ret = read(fd, msg, sizeof(msg));if( ret < 0 ){perror("read fail ");exit(1);}struct bufferevent* bev = (struct bufferevent*)arg;//把終端的消息發送給服務器端 bufferevent_write(bev, msg, ret); }void server_msg_cb(struct bufferevent* bev, void* arg) {char msg[1024];size_t len = bufferevent_read(bev, msg, sizeof(msg));msg[len] = '\0';printf("recv %s from server\n", msg); }void event_cb(struct bufferevent *bev, short event, void *arg) {if (event & BEV_EVENT_EOF)printf("connection closed\n");else if (event & BEV_EVENT_ERROR)printf("some other error\n");//這將自動close套接字和free讀寫緩沖區 bufferevent_free(bev);struct event *ev = (struct event*)arg;//因為socket已經沒有,所以這個event也沒有存在的必要了 event_free(ev); }typedef struct sockaddr SA; int tcp_connect_server(const char* server_ip, int port) {int sockfd, status, save_errno;struct sockaddr_in server_addr;memset(&server_addr, 0, sizeof(server_addr) );server_addr.sin_family = AF_INET;server_addr.sin_port = htons(port);status = inet_aton(server_ip, &server_addr.sin_addr);if( status == 0 ) //the server_ip is not valid value {errno = EINVAL;return -1;}sockfd = ::socket(PF_INET, SOCK_STREAM, 0);if( sockfd == -1 )return sockfd;status = ::connect(sockfd, (SA*)&server_addr, sizeof(server_addr) );if( status == -1 ){save_errno = errno;::close(sockfd);errno = save_errno; //the close may be errorreturn -1;}evutil_make_socket_nonblocking(sockfd);return sockfd; }

服務器端代碼:

#include<stdio.h> #include<string.h> #include<errno.h>#include<event.h> #include<event2/bufferevent.h>void accept_cb(int fd, short events, void* arg); void socket_read_cb(bufferevent* bev, void* arg); void event_cb(struct bufferevent *bev, short event, void *arg); int tcp_server_init(int port, int listen_num);int main(int argc, char** argv) {int listener = tcp_server_init(9999, 10);if( listener == -1 ){perror(" tcp_server_init error ");return -1;}struct event_base* base = event_base_new();//添加監聽客戶端請求連接事件struct event* ev_listen = event_new(base, listener, EV_READ | EV_PERSIST,accept_cb, base);event_add(ev_listen, NULL);event_base_dispatch(base);event_base_free(base);return 0; }void accept_cb(int fd, short events, void* arg) {evutil_socket_t sockfd;struct sockaddr_in client;socklen_t len = sizeof(client);sockfd = ::accept(fd, (struct sockaddr*)&client, &len );evutil_make_socket_nonblocking(sockfd);printf("accept a client %d\n", sockfd);struct event_base* base = (event_base*)arg;bufferevent* bev = bufferevent_socket_new(base, sockfd, BEV_OPT_CLOSE_ON_FREE);bufferevent_setcb(bev, socket_read_cb, NULL, event_cb, arg);bufferevent_enable(bev, EV_READ | EV_PERSIST); }void socket_read_cb(bufferevent* bev, void* arg) {char msg[4096];size_t len = bufferevent_read(bev, msg, sizeof(msg));msg[len] = '\0';printf("recv the client msg: %s", msg);char reply_msg[4096] = "I have recvieced the msg: ";strcat(reply_msg + strlen(reply_msg), msg);bufferevent_write(bev, reply_msg, strlen(reply_msg)); }void event_cb(struct bufferevent *bev, short event, void *arg) {if (event & BEV_EVENT_EOF)printf("connection closed\n");else if (event & BEV_EVENT_ERROR)printf("some other error\n");//這將自動close套接字和free讀寫緩沖區 bufferevent_free(bev); }typedef struct sockaddr SA; int tcp_server_init(int port, int listen_num) {int errno_save;evutil_socket_t listener;listener = ::socket(AF_INET, SOCK_STREAM, 0);if( listener == -1 )return -1;//允許多次綁定同一個地址。要用在socket和bind之間 evutil_make_listen_socket_reuseable(listener);struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_addr.s_addr = 0;sin.sin_port = htons(port);if( ::bind(listener, (SA*)&sin, sizeof(sin)) < 0 )goto error;if( ::listen(listener, listen_num) < 0)goto error;//跨平臺統一接口,將套接字設置為非阻塞狀態 evutil_make_socket_nonblocking(listener);return listener;error:errno_save = errno;evutil_closesocket(listener);errno = errno_save;return -1; }

高等:

客戶端代碼:

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 }

服務器端代碼:

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 }

?

轉載于:https://www.cnblogs.com/mayingkun/p/7292002.html

總結

以上是生活随笔為你收集整理的Libevent使用例子,从简单到复杂的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。