epoll中ET和LT模式的区别
2016-12-19 11:40
441 查看
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <fcntl.h> #include <stdlib.h> #include <sys/epoll.h> #include <pthread.h> /*宏定义区*/ #define MAX_EVENT_NUMBER 1024 #define BUFFER_SIZE 10 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 enable_et) { epoll_event event; event.data.fd = fd; event.events = EPOLLIN; if(enable_et) { event.events |= EPOLLET; } epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event); setnonblocking(fd); } void lt(epoll_event* events,int number,int epollfd,int listenfd) { char buf[BUFFER_SIZE]; for(int i = 0;i<number;i++) { int sockfd = events[i].data.fd; if(sockfd == listenfd) { struct sockaddr_in client_address; socklen_t client_addrlen = sizeof(sockaddr_in); int connfd = accept(listenfd,(struct sockaddr*)&client_address,&client_addrlen); //将fd加入到epoll的内核事件表中 addfd(epollfd,connfd,false); } else if(events[i].events & EPOLLIN) { //只要socket读缓存中还有未读取的数据,这段代码就会一直被触发 printf("event trigger once\r\n"); memset(buf,0,BUFFER_SIZE); int ret = recv(sockfd,buf,BUFFER_SIZE,0); if(ret < 0) { close(sockfd); continue; } printf("get %d bytes of content: %s\r\n",ret,buf); } else { printf("something else happened\r\n"); } } } /*et工作模式*/ void et(epoll_event* events,int number,int epollfd,int listenfd) { char buf[BUFFER_SIZE]; for(int i = 0;i<number;i++) { int sockfd = events[i].data.fd; if(sockfd == listenfd) { struct sockaddr_in client_address; socklen_t client_addrlen = sizeof(sockaddr_in); int connfd = accept(listenfd,(struct sockaddr*)&client_address,&client_addrlen); //将fd加入到epoll的内核事件表中 addfd(epollfd,connfd,true); } else if(events[i].events & EPOLLIN) { /*这段代码不会被重复触发,所以我们要循环读取数据,以确保socket读缓存中的所有数据被读出*/ printf("event trigger once\r\n"); while(1) { memset(buf,0,BUFFER_SIZE); int ret = recv(sockfd,buf,BUFFER_SIZE,0); if(ret < 0 ) { if((errno == EAGAIN) || (errno == EWOULDBLOCK)) { printf("read later\r\n"); break; } close(sockfd); break; } else if(0 == ret) { close(sockfd); } else { printf("get %d bytes of content: %s\r\n",ret,buf); } } } } } int main(int argc,char* argv[]) { if(argc <=2) { printf("usage:ddddd"); return 1; } const char* ip = argv[1]; int port = atoi(argv[2]); int ret = 0; struct sockaddr_in address; bzero(&address,sizeof(address)); address.sin_family = AF_INET; inet_pton(AF_INET,ip,&address.sin_addr); address.sin_port = htons(port); int listenfd = socket(AF_INET,SOCK_STREAM,0); assert(listenfd >=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,true); while(1) { int ret = epoll_wait(epollfd,events,MAX_EVENT_NUMBER,-1); //判断返回值 if(ret < 0) { printf("epoll failure!"); break; } //lt(events,ret,epollfd,listenfd); et(events,ret,epollfd,listenfd); } close(listenfd); return 0; }
使用客户端进行连接,每次发送大于10个字节的数字.
et模式截图如下:
lt模式截图如下:
lt模式只要有数据没有读完,就一直有事件来通知.
做实验是为了更好的理解网络编程中的具体问题,加油,小胖子,哈哈
相关文章推荐
- (转) epoll的LT和ET模式的区别
- epoll 的 Et与lt模式的区别
- Epoll在LT和ET模式下的读写方式和区别
- I/O多路复用之select、epoll的实现和区别 ,ET与LT模式
- 【服务器编程】EPOLL的LT和ET模式的区别和理解
- 【服务器编程】EPOLL的LT和ET模式的区别和理解
- epoll ET模式和LT模式
- [转]关于EPOLL的ET与LT工作模式及其他细节
- epoll的LT和ET模式
- epoll在LT和ET模式下的读写方式
- 【转载】epoll在LT和ET模式下的读写方式
- EPOLL的ET和LT模式
- 关于EPOLL的ET与LT工作模式及其他细节
- epoll机制:epoll_create、epoll_ctl、epoll_wait、close(在epoll的ET模式下,read和write或send和recv当返回值<0且errno=EAGAIN
- 关于EPOLL的ET与LT工作模式及其他细节
- epoll在LT和ET模式下的读写方式
- epoll的ET和LT模式
- epoll的ET和LT模式详解
- Epoll 的LT和ET模式
- epoll的ET和LT模式详解