Libevent实现TCP客户端服务器
17-libevent实现Tcp服务器流程_bilibili_哔哩哔哩_bilibili
1.服务器端实现流程
1.创建 event_base
2.创建服务器连接监听器 evconnlister_new_bind() ;
3.在 evconnlister_new_bind 的回调函数中,处理接受连接后的操作
4.回调函数被调用,说明有一个新客户端连接上来。会得到一个新fd,用于跟客户端通信(读、写)
5.使用 bufferevnet_socket_new()创建一个新bufferevnet事件,将fd 封装到这个事件对象中
6.使用 bufferevent_setcb 给这个事件对象的 read、write、event 设置回调
7.设置 bufferevnet 的读写缓冲区 enable/disable
8.接受、发送数据 bufferevent_read()/bufferevent_write()
9.启动循环监听
10.释放资源
2.服务器端代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
| #include<event2/listener.h> #include<event2/bufferevent.h> #include<event2/event.h> #include<sys/epoll.h> #include<sys/select.h> #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<fcntl.h> #include<errno.h> #include<string.h> #include<dirent.h> #include<sys/stat.h> #include<wait.h> #include<sys/mman.h> #include<signal.h> #include<pthread.h> #include<sys/socket.h> #include<arpa/inet.h> #include<ctype.h> #include<strings.h> #include<netinet/ip.h> #define SERV_PORT 9527
void read_cb(struct bufferevent *bev,void *arg) { char buf[1024]={0}; bufferevent_read(bev,buf,sizeof(buf)); printf("client say:%s\n",buf);
char *p="我是服务器,已经成功收到你发送的数据"; bufferevent_write(bev,p,strlen(p)+1); sleep(1); }
void write_cb(struct bufferevent *bev,void *arg) { }
void event_cb(struct bufferevent *bev,short events,void *arg) { if(events & BEV_EVENT_EOF) printf("连接关闭"); else if(events&BEV_EVENT_ERROR) printf("other error");
bufferevent_free(bev);
printf("buffevent 资源已经被释放..\n"); }
void cb_listener( struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *addr, int len,void *ptr) { printf("connect new client\n"); struct event_base *base=(struct event_base *)ptr; struct bufferevent *bev; bev=bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE); bufferevent_setcb(bev,read_cb,write_cb,event_cb,NULL); bufferevent_enable(bev,EV_READ);
}
int main(int argc,char * argv[]) { struct sockaddr_in serv; memset(&serv,0,sizeof(serv)); serv.sin_family=AF_INET; serv.sin_port=htons(SERV_PORT); serv.sin_addr.s_addr=htonl(INADDR_ANY); struct event_base* base; base=event_base_new(); struct evconnlistener *listener; listener=evconnlistener_new_bind(base,cb_listener,base, LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,36, (struct sockaddr *)&serv,sizeof(serv)); event_base_dispatch(base); evconnlistener_free(listener); event_base_free(base);
return 0; }
|
运行结果:

3.客户端实现流程
1.创建 event_base
2.使用 bufferevnet_socket_new()创建一个用跟服务器通信的 bufferevnet 事件对象+
3.使用 bufferevnet_socket_connect()连接 服务器
4.使用 bufferevent_setcb()给 bufferevnet 对象的 read、write、event 设置回调
5.设置 bufferevnet 对象的读写缓冲区 enable/disable
6.接受、发送数据 bufferevent_read()/bufferevent_write()
7.释放资源
4.客户端代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
| #include<event2/listener.h> #include<event2/bufferevent.h> #include<event2/event.h> #include<sys/epoll.h> #include<sys/select.h> #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<fcntl.h> #include<errno.h> #include<string.h> #include<dirent.h> #include<sys/stat.h> #include<wait.h> #include<sys/mman.h> #include<signal.h> #include<pthread.h> #include<sys/socket.h> #include<arpa/inet.h> #include<ctype.h> #include<strings.h> #include<netinet/ip.h> #define SERV_PORT 9527
void read_cb(struct bufferevent *bev, void *arg) { char buf[1024] = {0}; bufferevent_read(bev, buf, sizeof(buf));
printf("fwq say:%s\n", buf);
bufferevent_write(bev, buf, strlen(buf)+1); sleep(1); }
void write_cb(struct bufferevent *bev, void *arg) { }
void event_cb(struct bufferevent *bev, short events, void *arg) { if (events & BEV_EVENT_EOF) { printf("connection closed\n"); } else if(events & BEV_EVENT_ERROR) { printf("some other error\n"); } else if(events & BEV_EVENT_CONNECTED) { printf("已经连接服务器...\\(^o^)/...\n"); return; } bufferevent_free(bev); }
void read_terminal(evutil_socket_t fd,short what,void *arg) { char buf[1024]={0}; int len=read(fd,buf,sizeof(buf));
struct bufferevent *bev=(struct bufferevent*)arg; bufferevent_write(bev,buf,len+1);
}
int main(int argc,char * argv[]) { struct event_base * base=NULL; base=event_base_new(); int fd=socket(AF_INET,SOCK_STREAM,0); struct bufferevent *bev=NULL; bev=bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE); struct sockaddr_in serv; memset(&serv,0,sizeof(serv)); serv.sin_family=AF_INET; serv.sin_port=htons(9527); inet_pton(AF_INET,"127.0.0.1",&serv.sin_addr.s_addr);
bufferevent_socket_connect(bev,(struct sockaddr*)&serv, sizeof(serv)); bufferevent_setcb(bev,read_cb,write_cb,event_cb,NULL); bufferevent_enable(bev,EV_READ); struct event*ev=event_new(base,STDIN_FILENO,EV_READ|EV_PERSIST,read_terminal,bev); event_add(ev,NULL);
event_base_dispatch(base);
event_free(ev);
event_base_free(base);
return 0; }
|
运行结果:
