Socket条件就绪

读就绪

  1. 当前接受缓冲区的数据量大于SO_RCVLOWAT(接受低水位线,默认1字节)
  2. 收到FIN段 (如果我们没有close掉这个socket,它就一直处于就绪状态使epoll每次返回就绪事件的时候都会包含它)
  3. 该socket 上产生了一个未处理的error
  4. listen_socket的完全连接队列有相应的节点

写就绪

  1. 发送缓冲区内空闲的空间大于SO_SNDLOWAT的值(发送缓冲区低水位线默认1)
  2. 半关闭半打开连接,直接再次写入,条件也就绪并触发SIGPIPE(默认半大开半关闭第一次些收到RST,第二次写内核触发SIGPIPE信号默认终止程序)
  3. 一个未处理的error
  4. 一个非阻塞的套接字去调用connect,无论成功和失败都是写就绪的

获取error状态并消除

socket的error状态是可以清除的,通过调用getsockopt函数使用SO_ERROR选项即可

SO_SNDLOWAT

  对于这个选项Linux是不支持这个选项的修改的,如果我们修改是会收到ENOPROTOOPT错误。

SO_RCVLOWAT

   The select(2) and poll(2) system calls currently do not respect the SO_RCVLOWAT setting on Linux, and mark a socket readable when even a single byte of data is available
  上面虽然是man手册对于这个选项的解释,它说对于 poll 和 select系统调用是不支持SO_RCVLOWAT选项的,也就是说即使我们设置了这个选项,它也不会生效,比如我们设置为500,理论上只有接受缓冲区数据大于等于500后才会收到读就绪,但是实际上有1个字节到达后就可以收到读就绪了。
  上面这段是man手册的描述,但是这个man手册比较老了,这个bug在 内核版本2.6.28 后就被修复了:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c7004482e8dc
  也就是说我们高于这个版本还是会生效的

对于这个LOWAT的设置

  对于SO_RCVLOWAT来讲,如果我们提供这个限制的值,从某种程度上可以减少系统调用的次数提高性能

参考

https://www.ibm.com/support/knowledgecenter/en/SSB23S_1.1.0.14/gtpc1/gtpc1mst86.html
https://github.com/wahern/cqueues/issues/163

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页