IOCP、AcceptEx、重叠和 WSAEINVAL

Posted

技术标签:

【中文标题】IOCP、AcceptEx、重叠和 WSAEINVAL【英文标题】:IOCP, AcceptEx, overlapped and WSAEINVAL 【发布时间】:2013-12-31 21:52:44 【问题描述】:

我有一个使用 IOCP、套接字和重叠的服务器。最初一切都很好。侦听套接字使用 IOCP 上的 AcceptEx 传递给新创建的套接字。我可以很好地处理数千个连接。

当服务器进程处理落后时,它会关闭并断开监听端口。当它赶上来时,它将使用新的 IOCP 重新建立侦听端口。

我遇到的问题是,在重新建立侦听端口后,新连接到达后,我尝试使用与上述完全相同的代码路径来接受。 AcceptEx 失败并显示 WSAEINVAL。

我知道我遗漏了一些细节(魔鬼总是在细节中,不是吗?)——但希望能在我应该寻找的地方提供帮助。

如果有好奇的人想了解更多信息,我很乐意提供。

【问题讨论】:

“断开监听端口”没有意义,你不能断开一个端口,只能断开一个连接的套接字。不说了,贴代码。 删除端口 -- 因为不再监听。恐怕代码相当丰富。我不是原作者,只是修复它的咕噜声。 “删除端口”也没有任何意义。我认为他的意思是“关闭监听套接字”和/或关闭 IOCP。我不确定。 粗鲁的人群。但我怀疑措辞精度是必要的,或者有太多的回旋余地或解释。关闭监听套接字是正确的。 netstat 将不再显示正在监听的端口。当内部情况发生变化,服务器开始监听端口时,AcceptEx 在接受新连接时失败。 如果您认为 windows 标记人群很粗糙,请尝试使用标记为 C++ 的问题提出模棱两可的问题。那些家伙重新定义了严厉的爱。但我离题了......无论如何,如果你没有展示任何证明问题的最小示例代码,我必须使用我的精神力量。我的通灵能力表明,您作为第一个参数传递给 AcceptEx 的套接字标识符是您在返回侦听新套接字之前关闭的套接字的句柄。 【参考方案1】:

如果您没有显示任何源代码,很难猜测您的问题可能是什么,但是...

    无需关闭侦听套接字,只需停止发布新的 AcceptEx() 调用,服务器将无法接受任何新连接。

    如果您真的想关闭侦听套接字,请不要关闭 IOCP,并确保在重新创建侦听套接字时使用相同的 IOCP。

【讨论】:

谢谢伦。分布式应用程序的架构是关闭侦听套接字,以便客户端不再(立即)连接并负载平衡/故障转移到另一台服务器。至于第 2 部分——为什么重用相同的 IOCP 很重要?目前,新的 IOCP 与重新建立的侦听端口相关联。 足够公平地重新关闭监听套接字。如果您只是停止发出 AcceptEx() ,那么客户端连接尝试将需要更长的时间才能超时,因此您的故障转移不会那么有效。没有理由更改 IOCP,毕竟,您可能对所有数据流 I/O 使用相同的 IOCP。我不确定“接受的套接字”是否需要与与侦听套接字相同的 IOCP 相关联,但如果是这样,这可能是您的问题的原因......(我只是试图删除不必要的更改以缩小范围问题的原因)。【参考方案2】:

我会回答我自己的问题,因为我已经弄清楚了根本问题是什么。对问题至关重要但在问题陈述中未说明的一件事是服务器具有子进程。

事实证明,虽然 windows 中的默认行为是不让子进程继承句柄,但 winsock 的行为恰恰相反:除非在创建时明确设置为 no-inherit,否则句柄会被子进程继承。

创建带有不可继承句柄的套接字可以解决这个问题。我希望这可以帮助遇到这个问题的人。

【讨论】:

以上是关于IOCP、AcceptEx、重叠和 WSAEINVAL的主要内容,如果未能解决你的问题,请参考以下文章

网络模型之IOCP与扩展函数

AcceptEx与完成端口结合实例

IOCP陷阱

没有完成键的 IOCP 通知

并发程序设计6:IOCP

如何使用 IOCP 获取客户端真实 IP 地址和端口?