为什么IO复用要搭配非阻塞IO和应用层buffer

为什么IO多路复用要搭配非阻塞IO

  • select、poll_wait、epoll_wait返回可读≠read去读的时候能读到。如果不用非阻塞,程序会永远卡在read上。以上情况可能出现在多进程同时监听一个socket,只有一个进程可以accept,别的都会block。
  • 假如socket的读缓冲区已经有足够多的数据,需要read多次才能读完,如果是非阻塞可以在循环里读取,不用担心阻塞在read上,等到errno被置为EWOULDBLOCK的时候break,安全返回select。但如果是阻塞IO,只敢读取一次,因为如果读取没有数据的fd,read会阻塞,无法返回select,这样就只能期待着多次从select返回,每次只读一次,效率低下。而且,如果是ET模式,还会造成数据无人处理,导致饥饿。

为什么non-blocking网络编程中应用层buffer是必须的

首先,multiplex的核心思想是——用一个线程去同时对多个socket连接服务,即甩thread/process资源(因为传统的模式是一个thread/process只对一个connection服务),而想要做到这一点,thread/process就不能阻塞在某一个socket的read或write上,所以就要用到非阻塞IO原因见上。那么现在假设你要向一个socket发送100kb的数据,但是write调用中,操作系统只接受了80kb的数据,原因可能是受制于TCP的流量控制等等,现在你有两个选择 1.等——你可以while这个write调用,但你不知道要等多久,这取决于对方什么时候收到之前的报文并且滑动窗口,而且这样也浪费了处理别的socket的时间。 2.把剩下的20kb存起来,下次再发,具体一点就是把这20kb保存在这个TCPconnection的output buffer里,并且注册POLLOUT事件,这样select下次返回的时候就还会来发送这20kb的数据,也不会影响别的socket的监听。
至于为什么需要inputbuffer 那是因为TCP是一个没有边界的字节流协议,不可能一个数据报就是一个请求。

猜你喜欢

转载自blog.csdn.net/qq_33113661/article/details/88533686