libevent實現C/S模型
阿新 • • 發佈:2018-12-20
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <event2/event.h> #include <event2/bufferevent.h> #define LISTEN_PORT 8000 #define LIATEN_BACKLOG 32 /********************************************************************************* * 函式宣告 **********************************************************************************/ //accept回撥函式 void do_accept_cb(evutil_socket_t listener, short event, void *arg); //read 回撥函式 void read_cb(struct bufferevent *bev, void *arg); //error回撥函式 void error_cb(struct bufferevent *bev, short event, void *arg); //write 回撥函式 void write_cb(struct bufferevent *bev, void *arg); /********************************************************************************* * 函式體 **********************************************************************************/ //accept回撥函式 void do_accept_cb(evutil_socket_t listener, short event, void *arg) { //傳入的event_base指標 struct event_base *base = (struct event_base*)arg; struct sockaddr_in sin; //宣告地址 socklen_t slen = sizeof(sin); //地址長度宣告 //接收客戶端,並返回新的套接字conn_fd用於通訊 evutil_socket_t conn_fd= accept(listener, (struct sockaddr *)&sin, &slen); if (conn_fd< 0) { perror("error accept"); return; } printf("new client[%u] connect success \n", conn_fd); //使用conn_fd建立bufferevent,並將bufferevent也安插到base上 struct bufferevent *bev = bufferevent_socket_new(base, conn_fd, BEV_OPT_CLOSE_ON_FREE); bufferevent_setcb(bev, read_cb, NULL, error_cb, arg); //設定回撥函式read_cb \ error_cb bufferevent_enable(bev, EV_READ | EV_WRITE | EV_PERSIST);//啟用永久read/write } //read 回撥函式 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); //通過傳入引數bev找到socket fd while (n = bufferevent_read(bev, line, MAX_LINE)) { line[n] = '\0'; printf("fd=%u, read line: %s\n", fd, line); bufferevent_write(bev, line, n); //將獲取的資料回射給客戶端 } } //error回撥函式 void error_cb(struct bufferevent *bev, short event, void *arg) { //通過傳入引數bev找到socket fd evutil_socket_t fd = bufferevent_getfd(bev); //cout << "fd = " << fd << endl; 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); } //write 回撥函式 void write_cb(struct bufferevent *bev, void *arg) { char str[1024]; evutil_socket_t fd = bufferevent_getfd(bev);//通過傳入引數bev找到socket fd printf("輸入資料:"); scanf("%s",str); bufferevent_write(bev, &str, sizeof(str)); } int main() { evutil_socket_t listener; listener = socket(AF_INET, SOCK_STREAM, 0); 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(LISTEN_PORT); if (bind(listener, (struct sockaddr *)&sin, sizeof(sin)) < 0) { perror("bind"); return 1; } if (listen(listener, 1000) < 0) { perror("listen"); return 1; } printf("Listening...\n"); evutil_make_socket_nonblocking(listener); struct event_base *base = event_base_new(); //監聽套接字listener可讀事件:一旦有client連線,就會呼叫do_accept_cb回撥函式 struct event *listen_event = event_new(base, listener, EV_READ | EV_PERSIST, do_accept_cb, (void*)base); event_add(listen_event, NULL); event_base_dispatch(base); return 0; }