原理参考该博客
从man手册中,得到ET和LT的具体描述如下
}
具体请看代码:
#include <iostream> #include <fcntl.h> #include <assert.h> #include <sys/socket.h> #include <arpa/inet.h> #include <sys/epoll.h> #include <sys/types.h> #include <fcntl.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <memory.h> #include <errno.h> using namespace std; void setnonblocking(int fd)//设置fd为非阻塞 { int flag = fcntl(fd,F_GETFL); if(flag < 0)printf("fcntl error\n"); flag = fcntl(fd,F_SETFL,flag|O_NONBLOCK); if(flag < 0)printf("fcntl error\n"); } void addfd(int epollfd,int fd,bool UES_ET)//添加fd到epoll中,UES_ET表示是否使用ET模式 { struct epoll_event event; event.data.fd = fd; event.events = EPOLLIN; if(UES_ET)event.events |= EPOLLET; epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event); setnonblocking(fd); } void lt(epoll_event* events,int num,int epollfd,int listenfd)//水平模式 { int i; for(i = 0;i < num;i++) { int fd = events[i].data.fd; if(fd == listenfd)//新连接到达 { struct sockaddr_in client; socklen_t client_len = sizeof(client); int connfd = accept(listenfd,(struct sockaddr*)&client,&client_len); assert(connfd != -1); addfd(epollfd,connfd,false); } else { int buffer_len = 10; char buffer[buffer_len]; if(events[i].events & EPOLLIN) { int count = recv(fd,buffer,buffer_len-1,0); if(count < 0) { printf("recv error\n"); close(fd); } else if(count == 0) { printf("client close\n"); close(fd); } else { buffer[count] = '\0'; printf("receive %d byte char ,there are :%s\n",count,buffer); } } } } } void et(epoll_event* events,int num,int epollfd,int listenfd) { int i; for(i = 0;i < num;i++) { int fd = events[i].data.fd; if(fd == listenfd) { int connfd = accept(listenfd,NULL,NULL); assert( connfd > 0); addfd(epollfd,connfd,true);//开启ET模式 } else { if(events[i].events & EPOLLIN) { int buffer_len = 10; char buffer[buffer_len]; while(true)//读完所有数据 { int count = recv(fd,buffer,buffer_len-1,0); if(count < 0) { if(errno == EAGAIN || errno == EWOULDBLOCK) printf("there is no left data\n"); else { printf("receive error\n"); close(fd); } break; } else if(count == 0) { close(fd); printf("client close\n"); break; } else { buffer[count] = '\0'; printf("receive %d byte char ,there are :%s\n",count,buffer); } } } } } } int main(int argc,char* argv[]) { if(argc != 3)printf("usage %s ip_address port\n",basename(argv[0])); struct sockaddr_in server; bzero(&server,sizeof(server)); server.sin_family = AF_INET; server.sin_port = htons(atoi(argv[2])); inet_pton(AF_INET,argv[1],&server.sin_addr); int listenfd = socket(AF_INET,SOCK_STREAM,0); assert(listenfd >= 0); int opt = 1; int res = setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));//设置地址重用 assert(res == 0); socklen_t addrlen = sizeof(server); res = bind(listenfd,(struct sockaddr *)&server,addrlen); assert(res != -1); res = listen(listenfd,100); assert(res != -1); int epollfd = epoll_create(100); addfd(epollfd,listenfd,true);//连接只会到达一次,所以用ET模式 int MAX_EVENTS = 10; epoll_event events[MAX_EVENTS]; while(true) { int num = epoll_wait(epollfd,events,MAX_EVENTS,-1); if(num < 0)break; //lt(events,num,epollfd,listenfd); et(events,num,epollfd,listenfd); } }客户端可以使用telnet模拟,telnet ip port 登陆后,输入数据即可