半开的套接字上的select()不会在close()上返回?

时间:2015-11-20 19:24:33

标签: linux sockets select

我在阻塞套接字上执行select()而没有超时select(sock+1, &rfd, NULL, NULL, NULL)

这发生在一个目标是分派传入数据的线程中。另一个监视线程是管理对等体的保持活动,当它检测到死连接时,它将关闭套接字。

在这种情况下,我希望select()-1返回。它在Windows上执行,但从不在Linux上运行,因此当对等体非优雅地消失时,调度线程将永远锁定。为了完整性,有待传输的待处理数据,我试图使用SO_LINGER,但这并没有改变任何东西。

问题可以通过在select()设置超时来解决,在关闭和超时之后的情况下,select()最终会以-1退出,但我想,在阅读文档时,没有超时的select()仍会在关闭时退出,即使对等方没有响应。

我是否滥用select()或是否有更好的方法来处理半开插座?

1 个答案:

答案 0 :(得分:1)

是的,你滥用了selectman select州:

  

如果select()监视的文件描述符在另一个线程中关闭,则结果未指定。在某些UNIX系统上,select()取消阻塞并返回,并指示文件描述符已准备就绪(后续I / O操作可能会因错误而失败,除非另一个文件描述符在返回的时间select()和执行了I / O操作)。在Linux(以及其他一些系统)上,关闭另一个线程中的文件描述符对select()没有影响。总之,任何依赖于此场景中特定行为的应用程序都必须被视为错误。

因此您无法关闭其他线程的连接。不幸的是poll有同样的问题。

修改

有几种可能的解决方案,我没有足够的有关您的应用程序的信息。可以考虑改变以下内容:

  • 如果您使用的是Linux或其他现代轮询机制,请使用epoll代替selectselect是一个非常古老的功能,它是在线程未被认真考虑时及时设计的。
  • 在选择线程和保持活动线程之间建立通信通道。当保持活动线程检测到死对等体时,不要关闭套接字本身,而是指示选择线程执行此操作。通常,它可以通过本地套接字完成。将本地套接字添加到选择描述符集中,当保持活动线程向其写入内容时,选择线程会唤醒并执行操作。