6

Twisted 包括一个在MsgWaitForMultipleObjects. 显然,反应器无法可靠地注意到 TCP 连接何时结束,至少在对等方发送一些字节然后快速关闭连接的情况下。似乎发生的是:

  1. 反应器MsgWaitForMultipleObjects使用一些套接字句柄和QS_ALLINPUT.
  2. 调用完成并指示处于此状态的套接字的句柄(即,有等待读取的字节并已被对等方关闭)处于活动状态。
  3. 反应器将此通知分派给通用 TCP 实现。
  4. TCP 实现从套接字读取可用字节。有一些,它们被传递到应用程序代码。
  5. 控制权返回到反应堆,最终MsgWaitForMultipleObjects再次调用。
  6. MsgWaitForMultipleObjectsnever 再次指示句柄处于活动状态。TCP 实现永远不会再次查看套接字,因此它永远无法检测到连接已关闭。

这使它看起来好像MsgWaitForMultipleObjects是一种边缘触发的通知机制。MSDN 文档说:

Waits until one or all of the specified objects are in the signaled state
or the time-out interval elapses.

这听起来不像是边缘触发。这听起来像是水平触发。

实际上是MsgWaitForMultipleObjects边缘触发的吗?还是它是水平触发的,并且这种不当行为是由其行为的其他方面引起的?

附录 WSAEventSelect 的 MSDN 文档解释了这里发生的事情,包括指出这FD_CLOSE基本上是一次性事件。在它发出一次信号后,你将永远不会再得到它。这在某种程度上解释了为什么 Twisted 有这个问题。MsgWaitForMultipleObjects不过,鉴于此限制,我仍然有兴趣了解如何有效使用。

4

1 回答 1

1

为了使用WSAEventSelect和区分活动,您需要调用WSAEnumNetworkEvents. 确保您正在处理报告的每个事件,而不仅仅是第一个事件。

WSAAsyncSelect便于查明原因,常与MsgWaitForMultipleObjects.

所以你可以使用WSAAsyncSelect而不是WSAEventSelect.

Also, I think you have a fundamental misunderstanding of the difference between edge-triggered and level-triggered. Your reasoning seems to be more related to auto-reset vs manual-reset events.

于 2011-09-29T16:14:59.307 回答