recv函数阻塞_Epoll水平触发+非阻塞IO的理解

recv函数阻塞_Epoll水平触发+非阻塞IO的理解_第1张图片

首先水平触发(LT)、边缘触发(ET)、阻塞IO、非阻塞IO概念我就不普及了,默认大家都懂了。经常有人会疑惑为什么ET要配合非阻塞IO?为什么ET加非阻塞IO性能更好?我就谈谈自己的理解吧。

首先我们考虑下面几种情况:

  1. 假设buffer有1024字节大小,一次读取的数据较小,小于1024:这种情况下LT、ET、阻塞和非阻塞其实都一样,没有区别。因为阻塞和非阻塞都是调用recv()函数,并且一次就能返回,并不会阻塞在这里。由于一次性读取完,epoll_wait上只会出现一次可读事件,这样ET和LT就没有任何区别了。
  2. 假设buffer有1024字节,一次读取的数据很大,超过1024的大小:这种情况就需要读取多次,也就是要调用多次recv函数,通常我们会用while循环一直读取,无论ET还是LT,这样LT模式就显得很鸡肋,所以一般不用LT。在ET模式下,(1)、如果用阻塞IO+while循环,当最后一个数据读取完后,程序是无法立刻跳出while循环的,因为阻塞IO会在 while(true){ int len=recv(); }这里阻塞住,除非对方关闭连接或者recv出错,这样程序就无法继续往下执行,这一次的epoll_wait没有办法处理其它的连接,会造成延迟、并发度下降。(2)、如果是非阻塞IO+while循环当读取完数据后,recv会立即返回-1,并将errno设置为EAGAIN或EWOULDBLOCK,这就表示数据已经读取完成,已经没有数据了,可以退出循环了。这样就不会像阻塞IO一样卡在那里,这就减少了不必要的等待时间,性能自然更高。
  3. LT模式就不细说了,用的很少。

总结下:

  1. 每次读取小数据,所有一切都一样,一次读完返回,不用while。
  2. 读大数据,LT用的很少,几乎都是ET,阻塞IO会卡在while里,非阻塞IO会立即返回,性能更好。

最后补充两种情况,

1.读数据时,如果缓冲区装满,write 会阻塞住,等待写缓冲区有空余可写,如果网络拥塞,数据迟迟没有被发送走,整个epoll连接都会中断。

2.epoll返回可读,数据可能因为各种原因被内核丢弃,这样你read的时候会一直卡在那里,整个epoll我也会被阻塞在那里。

你可能感兴趣的:(recv函数阻塞)