I/O複用___libevent
阿新 • • 發佈:2018-12-01
一、情景再現
典型的C/S模式是這樣的,不妨以多執行緒為例來說明:ser啟動一個專門用於處理cli連線請求的執行緒,一旦需要連線,就accept,與cli建立連線,連線好後將事物交付給其他執行緒去處理。
當我們從事件監聽的角度讀看待這個流程的話,伺服器端起始有兩處需要被監聽:1、until有了連線請求才去accept;2、連線建立好了之後,until有了資料傳輸才會有recv或者send操作。
二、程式碼實現
2.1 伺服器端
#include<iostream> #include<arpa/inet.h> #include<sys/socket.h> #include<event.h> #include<assert.h> using namespace std; void listen_cb(int fd, short event, void* arg); //是否需要accept void c_cb(int clifd, short event, void *arg); //是否需要recv int main() { struct event_base *lib = event_base_new(); //初始化libevent int fd = socket(AF_INET, SOCK_STREAM, 0); assert(-1 != fd); struct sockaddr_in ser; ser.sin_family = AF_INET; ser.sin_port = htons(6000); ser.sin_addr.s_addr = inet_addr("127.0.0.1"); int res = bind(fd, (struct sockaddr*)&ser, sizeof(ser)); assert(-1 != res); assert(-1 != listen(fd, 5)); //建立事件 struct event* listen_event = event_new(lib, fd, EV_READ|EV_PERSIST, listen_cb, lib); assert(NULL != listen_event); event_add(listen_event, NULL); //將事件新增到列表中去 event_base_dispatch(lib); //迴圈監聽 return 0; } //主要是監聽是否要accept() void listen_cb(int fd, short event, void *arg) { struct event_base* lib = (struct event_base*)arg; struct sockaddr_in cli; socklen_t len = sizeof(cli); int clifd = accept(fd, (struct sockaddr*)&cli, &len); assert(-1 != clifd); //針對是否需要向已連線的客戶端提供服務 struct event* cli_event = event_new(lib, clifd, EV_READ, c_cb, lib); assert(NULL != cli_event); event_add(cli_event, NULL); } //主要是監聽是否要recv或者send void c_cb(int clifd, short event, void *arg) { char buf[128] = {'\0'}; int n = recv(clifd, buf, 127, 0);//一旦連線好的客戶端不再發送資料n=0 if(n > 0) { cout<<buf<<endl; assert(-1 != send(clifd, "OK", sizeof("OK"), 0)); } else { close(clifd); } }
2.2客戶端
#include<iostream> #include<event.h> #include<sys/socket.h> #include<arpa/inet.h> //inet_addr() #include<assert.h> using namespace std; int main() { int fd = socket(AF_INET, SOCK_STREAM, 0); assert(-1 != fd); struct sockaddr_in ser; ser.sin_family = AF_INET; ser.sin_port = htons(6000); ser.sin_addr.s_addr = inet_addr("127.0.0.1"); int res= connect(fd, (struct sockaddr*)&ser, sizeof(ser)); assert(-1 != res); assert(-1 != send(fd, "hello", sizeof("hello"), 0)); char buf[128] = {'\0'}; int n = recv(fd, buf, 127, 0); if(n > 0); cout<<buf<<endl; return 0; }