https://zhuanlan.zhihu.com/p/21374980

===============================================

https://zhuanlan.zhihu.com/p/21619218?utm_medium=social&utm_source=wechat_session&from=timeline&isappinstalled=0&s_s_i=akD%2BEQGuE2ymUvWOlk%2BEkZpTXXDTr7pm24gvEBEAW%2Fg%3D&s_r=1

EPOLL事件的两种模型:

Level Triggered (LT) 水平触发
.socket接收缓冲区不为空 有数据可读 读事件一直触发
.socket发送缓冲区不满 可以继续写入数据 写事件一直触发
符合思维习惯,epoll_wait返回的事件就是socket的状态

关键是ET模型这里写的很好了   仔细体会 以后不会再复习了

Edge Triggered (ET) 边沿触发   
.socket的接收缓冲区状态变化时触发读事件,即空的接收缓冲区  刚接收到数据时触发读事件
.socket的发送缓冲区状态变化时触发写事件,即满的缓冲区  刚空出空间时触发读事件
仅在状态变化时触发事件

https://blog.csdn.net/linuxheik/article/details/73294658

这个文章写的也可以但是 没有上面的到位

由上面的情况可以看出 LE模式来数据时候 缓冲区不完全读取结束没有事情  下次该事件他还会继续触发     但是ET  (默认就是非阻塞情况哦  )则不行      必须 将缓冲区读取结束,读到EAGAIN | EWOULDBLOCK且 n  < 0   这样该socket连接的缓冲区 下次发生事件(即有数据)时候才会再次触发。 

ET 模型 LT 模型的处理方式代码

#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_addrlength = sizeof( client_address );
int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength );
addfd( epollfd, connfd, false );
}
else if ( events[i].events & EPOLLIN )
{//只要socket读缓存区中还有未读出的数据 这段代码就会不停的被触发 即使关闭了sock
printf( "event trigger once\n" );
memset( buf, '\0', BUFFER_SIZE );
int ret = recv( sockfd, buf, BUFFER_SIZE-1, 0 );
if( ret <= 0 )
{
close( sockfd );
continue;
}
printf( "get %d bytes of content: %s\n", ret, buf );
}
else
{
printf( "something else happened \n" );
}
}
} 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_addrlength = sizeof( client_address );
int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength );
addfd( epollfd, connfd, true );
}
else if ( events[i].events & EPOLLIN )
{ //for 循环到某个sock连接的缓存区有数据 可读那么就要 while读取读到缓存区没有数据 ET模式
//确保把socket缓冲区存储的数据读取结束 才break 退出while
printf( "event trigger once\n" );
while( 1 )
{
memset( buf, '\0', BUFFER_SIZE );
int ret = recv( sockfd, buf, BUFFER_SIZE-1, 0 );
if( ret < 0 )
{//非阻塞ET模式 下面成立表示sock缓冲区数据读取结束了 此后epoll_wait就能再次触发,就能再一次触发fd 上的EPOLLIN事件
if( ( errno == EAGAIN ) || ( errno == EWOULDBLOCK ) )
{ //无需关闭socket 只说明现在缓冲区没有数据可以读取了 等待下一次触发处理
printf( "read later\n" );
break;//这里 缓冲区数据读取over了 所以break掉当前读取sock的while循环
}
//返回-1 那么说明发生其他错误不是上面的两种错误直接关闭sock
close( sockfd );
break;
}
else if( ret == 0 )
{
close( sockfd );// ==0 ET模式返回0 表示对端已经关闭了
}
else
{ //接收ok
printf( "get %d bytes of content: %s\n", ret, buf );
}
}
}
else
{
printf( "something else happened \n" );
}
}
} int main( int argc, char* argv[] )
{
if( argc <= 2 )
{
printf( "usage: %s ip_address port_number\n", basename( argv[0] ) );
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( PF_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\n" );
break;
} //lt( events, ret, epollfd, listenfd );
et( events, ret, epollfd, listenfd );
} close( listenfd );
return 0;
}

  

和上面不相关

void handleRead(int efd, int fd) {
char buf[4096];
int n = 0;
while ((n=::read(fd, buf, sizeof buf)) > 0) {
if(output_log) printf("read %d bytes\n", n);
string& readed = cons[fd].readed;
readed.append(buf, n);
if (readed.length()>4) {
if (readed.substr(readed.length()-2, 2) == "\n\n" || readed.substr(readed.length()-4, 4) == "\r\n\r\n") {
//当读取到一个完整的http请求,测试发送响应
sendRes(fd);
}
}
}
//这里当socket缓冲区的数据被读取完毕了,return掉 但不能close fd 因为下次该sock缓冲区有数据还会再次触发
//ET 非阻塞就是要读到 EAGAIN 且 n < 0 就是将来sock缓冲区读彻底下次才触发
if (n<0 && (errno == EAGAIN || errno == EWOULDBLOCK))
return;
//实际应用中,n<0应当检查各类错误,如EINTR
if (n < 0) {
printf("read %d error: %d %s\n", fd, errno, strerror(errno));
}
close(fd);
cons.erase(fd);
}

  

epoll 中ET与LT 关于读取处理 复习的更多相关文章

  1. C#中常用的几种读取XML文件的方法

    1.C#中常用的几种读取XML文件的方法:http://blog.csdn.net/tiemufeng1122/article/details/6723764/

  2. C#中创建、打开、读取、写入、保存Excel的一般性代码

    ---转载:http://hi.baidu.com/zhaocbo/item/e840bcf941932d15fe358228 1. Excel对象微软的Excel对象模型包括了128个不同的对象,从 ...

  3. C#中内嵌资源的读取

    起因 作为一个从Cpper转到C#并且直接从事WPF开发的萌新来说,正式编码过程中碰到了不少问题,一路上磕磕碰碰的.因为软件设计需求上的要求,需要将一些配置文件(XML.INI等)内嵌到程序中,等需要 ...

  4. python操作txt文件中数据教程[3]-python读取文件夹中所有txt文件并将数据转为csv文件

    python操作txt文件中数据教程[3]-python读取文件夹中所有txt文件并将数据转为csv文件 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 python操作txt文件中 ...

  5. ASP.NET CORE MVC 2.0 如何在Filter中使用依赖注入来读取AppSettings,及.NET Core控制台项目中读取AppSettings

    问: ASP.NET CORE MVC 如何在Filter中使用依赖注入来读取AppSettings 答: Dependency injection is possible in filters as ...

  6. Jar中的Java程序如何读取Jar包中的资源文件

    Jar中的Java程序如何读取Jar包中的资源文件 比如项目的组织结构如下(以idea中的项目为例): |-ProjectName |-.idea/  //这个目录是idea中项目的属性文件夹 |-s ...

  7. 其它课程中的python---6、python读取数据

    其它课程中的python---6.python读取数据 一.总结 一句话总结: 记常用和特例:慢慢慢慢的就熟了,不用太着急,慢慢来 库的使用都很简单:就是库的常用函数就这几个,后面用的时候学都来得及. ...

  8. epoll中et+多线程模式中很重要的EPOLL_ONESHOT实验

    因为et模式需要循环读取,但是在读取过程中,如果有新的事件到达,很可能触发了其他线程来处理这个socket,那就乱了. EPOLL_ONESHOT就是用来避免这种情况.注意在一个线程处理完一个sock ...

  9. Python中数据的保存和读取

    在科学计算的过程中,往往需要保存一些数据,也经常需要把保存的这些数据加载到程序中,在 Matlab 中我们可以用 save 和 lood 函数很方便的实现.类似的在 Python 中,我们可以用 nu ...

随机推荐

  1. MySQL安装与管理

    数据库服务器.数据库和表的关系 –所谓安装数据库服务器,只是在机器上装了一个数据库管理程序,这个管理程序可以管理多个数据库,一般开发人员会针对每一个应用创建一个数据库. –为保存应用中实体的数据,一般 ...

  2. PDG转PDF注定会文件膨胀、质量下降吗?

    作者:马健邮箱:stronghorse_mj@hotmail.com发布:2006.07.16更新:2006.07.20 事先声明: PDG文件是超星公司电子图书的专有格式,需要用超星公司的专用浏览器 ...

  3. 将Winform程序及dll打包成可执行的exe

    使用场景 通常开发的Winform程序,引用了其他类库后,在输出目录下都会产生很多DLL文件,exe执行时必须依赖这些DLL.想要Winform程序只有一个可执行exe文件,又不想打包成安装包,就可以 ...

  4. centos7.4版本安装nmon监控软件

    一.检查安装环境 # uname –a (查看操作系统信息,所检查服务器为64位操作系统) Linux iZ94pmb2p24Z 2.6.32-431.23.3.el6.x86_64 #1 SMP T ...

  5. html颜色设定 - 网址不见了看这里

  6. 【bzoj1965】: [Ahoi2005]SHUFFLE 洗牌 数论-快速幂-扩展欧几里得

    [bzoj1965]: [Ahoi2005]SHUFFLE 洗牌 观察发现第x张牌 当x<=n/2 x=2x 当x>n/2 x=2x-n-1 好像就是 x=2x mod (n+1)  就好 ...

  7. 文章推荐一个Java程序员跟大家谈谈从业心得

    一个Java程序员跟大家谈谈从业心得 2017-10-21 java那些事 java那些事 java那些事 微信号 csh624366188 功能介绍 分享java开发中常用的技术,分享软件开发中各种 ...

  8. zancun

    #include<iostream> #include<cstdio> using namespace std; ; int n; int avai[maxn], need[m ...

  9. 洛谷P2606 [ZJOI2010]排列计数(数位dp)

    题目描述 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案可能很 ...

  10. 生成对抗网络(GAN)相关链接汇总

    1.基础知识 创始人的介绍: “GANs之父”Goodfellow 38分钟视频亲授:如何完善生成对抗网络?(上) “GAN之父”Goodfellow与网友互动:关于GAN的11个问题(附视频) 进一 ...