赞
踩
bufferevent 帮我们更好的处理单纯的读写操作
evconnlistener_new_bind内部帮我们使用了socket的accept bind等函数
带有定时器超过时间没有读写操作就将断开连接。
bufferevent_set_timeouts
#include <iostream> #include <curl/curl.h> #include <assert.h> #include <event2/event.h> #include <event2/bufferevent.h> #include <event2/listener.h> #include <event2/thread.h> #include <sys/types.h> #include <error.h> #include <unistd.h> #include <string.h> void event_cb(struct bufferevent* bev, short event, void * arg ) { if ( event & BEV_EVENT_TIMEOUT ) printf("client timeout\n"); else if ( event & BEV_EVENT_EOF ) printf("connection closed\n"); else if ( event & BEV_EVENT_ERROR ) printf("some other error\n"); bufferevent_free(bev); } void socket_read_cb(struct 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\n",msg); char reply_msg[4096] = " received the msg : "; strcat(reply_msg+ strlen(reply_msg),msg); bufferevent_write(bev,reply_msg, strlen(reply_msg)); } void listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr*sock, int socklen, void*arg) { printf("accapt a client %d \n",fd); struct event_base* base = (struct event_base *)arg; struct bufferevent *bev = bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE); bufferevent_setcb(bev,socket_read_cb,NULL,event_cb,NULL); bufferevent_enable(bev,EV_READ | EV_PERSIST); struct timeval tv = {10,0}; bufferevent_set_timeouts (bev, &tv, 0); } 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; } 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); } int sockfd = *((int*)arg); //把终端的消息发送给服务器端 //为了简单起见,不考虑写一半数据的情况 write(sockfd, msg, ret); } void socket_read_cb(int fd , short events , void * arg ) { char msg[4096]; int len = read(fd, msg, sizeof(msg) - 1); if(len <= 0) { printf("some error happen when read\n"); return; } msg[len] = '\0'; printf("recv the client msg : %s\n", msg); } 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; /* * 很堵,被STDIN堵住了 //动态创建一个event结构体,并将其作为回调参数传递给 struct event* ev2 = event_new(NULL, -1, 0, NULL, NULL); struct event* ev = event_new(NULL, -1, 0, NULL, NULL); event_assign(ev2, base, STDIN_FILENO, EV_WRITE | EV_PERSIST, cmd_msg_cb, (void *)&sockfd); event_assign(ev, base, sockfd, EV_READ | EV_PERSIST, socket_read_cb, NULL); event_add(ev, NULL); event_add(ev2,NULL); */ struct 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 ); } int main() { /* int listener = tcp_server_init(5000,10); assert(listener != -1 ); struct event_base *base = event_base_new(); assert(base != NULL); //creatfifo((void*)base); struct event* listen_event; listen_event = event_new(base,listener,EV_READ|EV_WRITE|EV_PERSIST,accept_cb,(void*)base); */ struct sockaddr_in sin ; memset(&sin,0,sizeof(struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_port = htons(5000); struct event_base *base = event_base_new(); struct evconnlistener * listener = evconnlistener_new_bind(base,listener_cb,base, LEV_OPT_CLOSE_ON_FREE, 10, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)); //监听终端输入事件 event_base_dispatch(base); evconnlistener_free(listener); event_base_free(base); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。