一个采用EPOLLONETSHOT的例子:
epoll_oneshot._server.cpp服务端程序
[cpp] view plaincopy
#include#include #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_EVENT_NUMBER 1024//最大事件连接数 #define BUFFER_SIZE 1024//接收缓冲区大小 using namespace std; struct fds{//文件描述符结构体,用作传递给子线程的参数 int epollfd; int sockfd; }; int setnonblocking(int fd){//设置文件描述符为非阻塞 int old_option=fcntl(fd,F_GETFL); int new_option=old_option|O_NONBLOCK; fcntl(fd,F_SETFL,new_option); return old_option; } void addfd(int epollfd,int fd,bool oneshot){//为文件描述符添加事件 epoll_event event; event.data.fd=fd; event.events=EPOLLIN|EPOLLET; if(oneshot){//采用EPOLLONETSHOT事件 event.events|=EPOLLONESHOT; } epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event); setnonblocking(fd); } void reset_oneshot(int epollfd,int fd){//重置事件 epoll_event event; event.data.fd=fd; event.events=EPOLLIN|EPOLLET|EPOLLONESHOT; epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event); } void* worker(void* arg){//工作者线程(子线程)接收socket上的数据并重置事件 int sockfd=((fds*)arg)->sockfd; int epollfd=((fds*)arg)->epollfd;//事件表描述符从arg参数(结构体fds)得来 cout<<"start new thread to receive data on fd:"< =0); ret=bind(listenfd,(struct sockaddr*)&address,sizeof(address)); assert(ret!=-1); ret=listen(listenfd,5); assert(ret!=-1); epoll_event events[MAX_EVENT_NUMBER]; int epollfd=epoll_create(5); assert(epollfd!=-1); addfd(epollfd,listenfd,false);//不能将监听端口listenfd设置为EPOLLONESHOT否则会丢失客户连接 while(1){ int ret=epoll_wait(epollfd,events,MAX_EVENT_NUMBER,-1);//等待事件发生 if(ret<0){ cout<<"epoll error"<
epoll_oneshot_client.cpp客户端程序
#include#include #include #include #include #include #include #include #include #include #include #include #include #define BUFFER_SIZE 512 using namespace std; int main(int argc,char* argv[]){ if(argc<=2){ cout<<"argc<=2"< =0); int fd=open("epoll_oneshot_server.cpp",O_RDONLY);//打开一个文件并向服务端不断发送数据 if(connect(sockfd,(struct sockaddr*)&server_address,sizeof(server_address))<0){ cout<<"connect error "< 0){ send(sockfd,buf,strlen(buf),0); } } close(sockfd); return 0; }