套接字:不断让 POLLHUP 处于半关闭状态

Posted

技术标签:

【中文标题】套接字:不断让 POLLHUP 处于半关闭状态【英文标题】:socket: constantly getting POLLHUP on half-close 【发布时间】:2011-09-30 09:30:25 【问题描述】:

我写了一个套接字服务器,在 linux 上运行,但这可能不是 linux 规范。

我使用poll() 来检查客户端的状态。我的客户在发送请求后会主动(半)关闭。由于客户端的半关闭,服务器不断收到POLLHUPPOLLERR。我还看到POLLRDHUP,所以我知道这实际上是半关闭而不是连接关闭/重置。我的问题是我总是会收到这些事件,即使我已经从之前的民意调查中知道有一半关闭。

如何禁用此功能,以便不再收到 thisis 事件?我试图做额外的read() 并做一个shutdown(fd, SHUT_RD),但它似乎没有帮助。我不希望 poll 因我已经处理过的事件而醒来。

【问题讨论】:

我和你有类似的问题,我不想在 poll() 中获取 POLLHUP / POLLERR 并且只获取我选择的事件。不知道如何做到这一点 【参考方案1】:

一旦你接近一半,就停止在 readfds 集中包含 fd。 除了半关闭,没有什么可阅读的了。从这一点来看,您唯一感兴趣的就是“可写”事件。

【讨论】:

readfds(和单独的集合)仅适用于select,但你是对的,我刚刚遇到了一个错误,但仍在轮询读取.. 把我的头撞到墙上 :)【参考方案2】:

在返回标志中忽略POLLHUP。如果正确,现有代码将执行您想要的操作。

您将不断从poll()(EJP 的回答中概述)获得半关闭的事实是一项功能,而不是错误。它使您可以像对待文件结尾一样对待半封闭;这正是您想要的,因为它让您的应用程序读取套接字缓冲区中的最后一个字节而不是丢弃它们(这是 TCP 半关闭的正确语义)。

一旦达到“普通”文件结尾,poll() 将始终选择文件描述符作为准备读取。围绕poll() 的循环应该是read() 数据直到看到文件结尾,然后是close()。忽略POLLHUP 条件可以让您的程序在半关闭情况下使用相同的代码执行完全相同的操作,并获取套接字缓冲区中的最后一个字节。

同样,您应该在不关心POLLHUP 的情况下实现控制流。如果(仅当)您需要限制文件描述符(即当前无处可放入 read() 字节),然后从 poll() 集中删除该描述符,以便内核不会用准备读取的“中断”来打扰你,直到你再次告诉它(unthrottling)。所有数据都已经在套接字缓冲区中(这是POLLHUP 位所指示的)这一事实再次没有任何区别。

【讨论】:

抱歉,EJP 有正确的答案。就我而言,我不能close();有很多数据要发送。如果我将 fd 保留在读取集中,poll() 将立即返回...

以上是关于套接字:不断让 POLLHUP 处于半关闭状态的主要内容,如果未能解决你的问题,请参考以下文章

ZeroMQ 清理 PULL 套接字 - 半关闭

允许该应用创建网络套接字是啥意思

描述符就绪条件

多套接字监控

为啥在关闭客户端套接字时,他的进程会更改状态“Z”(僵尸)?

TCP,UDP协议下的socket通信