1.epoll的两种工作模式介绍

epoll的两种模式ET和LT:
LT模式(水平触发):是缺省的工作方式,并且同时支持block和non-block socket。在这种做法中,内核告诉你一个文件描述符是否就绪,然后可以对这个就绪的fd进行io操作,如果你不做任何操作,内核还会继续通知你的。(只要缓冲区有数据就会一直通知)
ET模式(边沿触发):是高速工作方式,只支持no-block socket。在这种模式下,当文件描述符从未就绪变为就绪时,内核会通过epoll告诉你。然后,内核会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知,知道你做了某些操作导致那个文件描述符不再为就绪状态了。(缓冲区有数据只会通知一次,之后再有数据才回通知)

2.测试ET模式和LT模式的区别

源代码(wrap相关文件在文章里):

#include"wrap.h"
#include<stdio.h>
#include<sys/epoll.h>
#include<errno.h>
#include<ctype.h>
int main(){int lfd;int ret;int n;int epfd;int i;int nready;int cfd;int sockfd;char buf[1024];socklen_t socklen;struct sockaddr_in svraddr;struct epoll_event ev;struct epoll_event events[1024];//创建sockelfd=socket(AF_INET,SOCK_STREAM,0);//设置端口复用int opt=1;setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(int));//绑定bzero(&svraddr,sizeof(svraddr));svraddr.sin_addr.s_addr=htonl(INADDR_ANY);svraddr.sin_port=htons(8888);svraddr.sin_family=AF_INET;Bind(lfd,(struct sockaddr*)&svraddr, sizeof(svraddr));//设置监听Listen(lfd,128);//创建一个epoll树epfd=epoll_create(1024);if(epfd<0){perror("create epoll error");return -1;}//将监听文件描述符上epoll树ev.events=EPOLLIN;ev.data.fd=lfd;epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&ev);while (1){nready=epoll_wait(epfd,events,1024,-1);if(nready<0){perror("epoll_wait error");if(errno==EINTR){continue;}break;}for(i=0;i<nready;i++){sockfd=events[i].data.fd;//有客户端请求到来if(sockfd==lfd){cfd=Accept(lfd,NULL,NULL);//将cfd对应的事件上树ev.data.fd=cfd;ev.events=EPOLLIN;//可读事件epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&ev);continue;}//有客户端发送数据到来memset(buf,0x00,sizeof(buf));//n=Read(sockfd,buf,sizeof(buf));n=recv(sockfd,buf,2,0);if(n<=0){printf("n==%d, buf==%s\n",n,buf);Close(sockfd);//将sockfd对应的事件节点从epoll树上删除epoll_ctl(cfd,EPOLL_CTL_DEL,sockfd,NULL);perror("read error or client error");continue;}else{printf("n==%d, buf==%s\n",n,buf);for(int k=0;k<n;k++){buf[k]=toupper(buf[k]);}//Write(sockfd,buf,n);send(sockfd,buf,n,0);}}}Close(epfd);Close(lfd);return 0;
}



可以发现执行了四次,epoll默认情况下为水平模式,在这种模式下,若数据一次性没有读完,缓冲区还有可读数据,则epoll_wait还会再次通知。如设置成ET模式:
源代码:

#include"wrap.h"
#include<stdio.h>
#include<sys/epoll.h>
#include<errno.h>
#include<ctype.h>
int main(){int lfd;int ret;int n;int epfd;int i;int nready;int cfd;int sockfd;char buf[1024];socklen_t socklen;struct sockaddr_in svraddr;struct epoll_event ev;struct epoll_event events[1024];//创建sockelfd=socket(AF_INET,SOCK_STREAM,0);//设置端口复用int opt=1;setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(int));//绑定bzero(&svraddr,sizeof(svraddr));svraddr.sin_addr.s_addr=htonl(INADDR_ANY);svraddr.sin_port=htons(8888);svraddr.sin_family=AF_INET;Bind(lfd,(struct sockaddr*)&svraddr, sizeof(svraddr));//设置监听Listen(lfd,128);//创建一个epoll树epfd=epoll_create(1024);if(epfd<0){perror("create epoll error");return -1;}//将监听文件描述符上epoll树ev.events=EPOLLIN;ev.data.fd=lfd;epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&ev);while (1){nready=epoll_wait(epfd,events,1024,-1);if(nready<0){perror("epoll_wait error");if(errno==EINTR){continue;}break;}for(i=0;i<nready;i++){sockfd=events[i].data.fd;//有客户端请求到来if(sockfd==lfd){cfd=Accept(lfd,NULL,NULL);//将cfd对应的事件上树ev.data.fd=cfd;ev.events=EPOLLIN | EPOLLET;//可读事件epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&ev);continue;}//有客户端发送数据到来memset(buf,0x00,sizeof(buf));//n=Read(sockfd,buf,sizeof(buf));n=recv(sockfd,buf,2,0);if(n<=0){printf("n==%d, buf==%s\n",n,buf);Close(sockfd);//将sockfd对应的事件节点从epoll树上删除epoll_ctl(cfd,EPOLL_CTL_DEL,sockfd,NULL);perror("read error or client error");continue;}else{printf("n==%d, buf==%s\n",n,buf);for(int k=0;k<n;k++){buf[k]=toupper(buf[k]);}//Write(sockfd,buf,n);send(sockfd,buf,n,0);}}}Close(epfd);Close(lfd);return 0;
}



若将epoll模式设置为ET模式,若读数据的时候一次性没有读完,则epoll_wait不再通知,知道下次有新的数据发来。

3.ET模式下的非阻塞模式

在ET模式下,需要循环读完数据,知道读完数据,但是读完数据会阻塞;若要一次性读完数据,还需要将通信文件描述符设置为非阻塞模式。
源代码:

#include"wrap.h"
#include<stdio.h>
#include<sys/epoll.h>
#include<errno.h>
#include<ctype.h>
#include<fcntl.h>
int main(){int lfd;int ret;int n;int epfd;int i;int nready;int cfd;int sockfd;char buf[1024];socklen_t socklen;struct sockaddr_in svraddr;struct epoll_event ev;struct epoll_event events[1024];//创建sockelfd=socket(AF_INET,SOCK_STREAM,0);//设置端口复用int opt=1;setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(int));//绑定bzero(&svraddr,sizeof(svraddr));svraddr.sin_addr.s_addr=htonl(INADDR_ANY);svraddr.sin_port=htons(8888);svraddr.sin_family=AF_INET;Bind(lfd,(struct sockaddr*)&svraddr, sizeof(svraddr));//设置监听Listen(lfd,128);//创建一个epoll树epfd=epoll_create(1024);if(epfd<0){perror("create epoll error");return -1;}//将监听文件描述符上epoll树ev.events=EPOLLIN;ev.data.fd=lfd;epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&ev);while (1){nready=epoll_wait(epfd,events,1024,-1);if(nready<0){perror("epoll_wait error");if(errno==EINTR){continue;}break;}for(i=0;i<nready;i++){sockfd=events[i].data.fd;//有客户端请求到来if(sockfd==lfd){cfd=Accept(lfd,NULL,NULL);//将cfd对应的事件上树ev.data.fd=cfd;ev.events=EPOLLIN | EPOLLET;//可读事件epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&ev);//将cfd设置为非阻塞int flag =fcntl(cfd,F_GETFL);flag |=O_NONBLOCK;fcntl(cfd,F_SETFL,flag);continue;}//有客户端发送数据到来memset(buf,0x00,sizeof(buf));while(1){//n=Read(sockfd,buf,sizeof(buf));n=Read(sockfd,buf,2);//读完数据if(n==-1){printf("read over, n=%d\n",n);break;}//对方关闭连接或者异常if(n==0||(n<0&&n!=-1)){printf("n==%d, buf==%s\n",n,buf);Close(sockfd);//将sockfd对应的事件节点从epoll树上删除epoll_ctl(cfd,EPOLL_CTL_DEL,sockfd,NULL);break;}else{printf("n==%d, buf==%s\n",n,buf);for(int k=0;k<n;k++){buf[k]=toupper(buf[k]);}Write(sockfd,buf,n);}}}}Close(epfd);Close(lfd);return 0;
}

epoll的ET工作模式和LT工作模式相关推荐

  1. rabbitmq几种工作模式_RabbitMQ六种队列模式-简单队列模式

    在官网的教程中,描述了如上六类工作队列模式: 简单队列模式:最简单的工作队列,其中一个消息生产者,一个消息消费者,一个队列.也称为点对点模式. 工作模式:一个消息生产者,一个交换器,一个消息队列,多个 ...

  2. apache 工作模式prefork进程模式和worker线程模式参式详解和推荐设置

    一apache工作模式: 1.prefork进程模式: prefork模式参数说明: prefork模式推荐设置: 二.apache worker模式: 1. 参数 三.prefork和worker模 ...

  3. 计算机网络对等模式,计算机网络有两种常用的工作模式,它们是对等模式和客户/服务器模式。QQ聊天属于________模式。...

    计算机网络有两种常用的工作模式,它们是对等模式和客户/服务器模式.QQ聊天属于________模式. 更多相关问题 Maria, Enclosed is the schedule for this y ...

  4. 密码库LibTomCrypt学习记录——(2.15)分组密码算法的工作模式——GCM加密认证模式

    GCM GCM是一种有大吞吐能力的加密认证模式.其中主要适用了CRT模式和类似CBC模式的GHASH模式.CRT模式基本上没有大多变化,GHASH则是利用有限域上的乘法进行HASH,此运算可以通常预先 ...

  5. 8086的两种工作模式_8086系统中最小模式与最大模式两种工作方式的主要区别是什么?...

    展开全部 最小模式和最大模式的主要区别为以下几方面: 1.处理系统方面 最小模式:系统里e68a843231313335323631343130323136353331333366306533就808 ...

  6. 计算机网络有客户 服务器和对等模式,四种网络工作模式有:对等模式、客户/服务器模式以及( )、( ),...

    四种网络工作模式有:对等模式.客户/服务器模式以及专用服务器模式和浏览器/服务器模式. 1.对等模式(P2P,peer-to-peer)是一种通信模式,其中每一方都拥有相同的功能,任何一方都可以启动通 ...

  7. 工作中的设计模式 —— 策略模式

    前言 返利网站 https://m.cpa5.cn/ 策略模式是一种行为设计模式,它能让你定义一系列算法,并将每种算法分别放入独立的类中,以使算法的对象能够相互替换. 使用场景 策略模式在工作中使用的 ...

  8. 计算机组成位模式,Pentium的工作模式-计算机组成原理与汇编语言-电子发烧友网站...

    7.4.1 实地址模式 1. 实地址模式的进入 在处理器复位后,处理器内部的CR0的PE位为0,表示此时处理器工作在实地址模式.同时,复位后的处理器的内部寄存器状态如表7.2所示. 2. 实地址模式下 ...

  9. EPPlus导出和Spire.Xls导入、导出Pdf/Image、调节工作簿比例和视图模式

    EPPLus导出的教程 ,总结的很详细: http://www.cnblogs.com/rumeng/p/3785775.html https://www.cnblogs.com/chenwolong ...

最新文章

  1. Ubuntu16.04 安装Qt
  2. 3D视觉工坊—助学助研计划正式启动!
  3. Pixhawk代码分析-启动代码及入口函数
  4. VS2003转VS2010 fatal error C1189: #error
  5. react学习(65)--ant design加载中
  6. 《C#高级编程》笔记系列第三弹
  7. c语言的一些字符串库函数的自己实现
  8. 43w+条手机电话号码归属地数据库免费下载·附区号邮编
  9. c语言打码软件官方下载,触动精灵人工打码软件
  10. 数据迁移 java_数据迁移的成功策略
  11. Python项目(Django):国内新冠肺炎疫情大数据可视化平台
  12. 如何将mp4视频格式转换成mov视频
  13. oracle编程弹框函数,取窗口句柄的api函数
  14. Sereja and Swaps
  15. 【Druid】(四)Apache Druid 部署和配置(单机版 / Docker 容器版 / Kubernetes 集群版)
  16. 计算机写给未来自己的一段话,现实,致自己 写给自己的霸气一段话汇总73句
  17. 今晚7:30 | IJCAI专场五!不见不散!
  18. Android正方形View
  19. matlab图片不覆盖,放置MATLAB图例,使其在图上不重叠
  20. A7139 无线通信驱动(STM32) 增加FIFO扩展模式,可以发送超大数据包

热门文章

  1. Android 自定义View实现圆形头像(适用于任意布局)
  2. learning的反义词英文_英语同义词反义词
  3. PHP实现生成推广海报的方法详解
  4. 七夕情节人,适合给IT男朋友送什么专属礼物?
  5. OSChina 周三乱弹 ——纪念Bob Taylor
  6. 不得不知道的一些Java学习资料
  7. 云南大学软件测试,云南大学《软件测试》软件测试期末报告.pdf
  8. 【网络聊天室】——基于socket编程的TCP/UDP网络聊天服务器
  9. 泊松噪声(附Matlab代码)
  10. Java安卓适配全面屏_Android APP全面屏适配技术要点