MsgWaitForMultipleObjects

MsgWaitForMultipleObjects

Twisted包含a reactor implemented on top of MsgWaitForMultipleObjects 。显然,至少在对等方发送一些字节然后迅速关闭连接的情况下, react 堆在可靠地通知TCP连接结束时会遇到问题。似乎发生的是:

  • The reactor calls MsgWaitForMultipleObjects with some socket handles and QS_ALLINPUT .
  • 调用已完成,并指示处于此状态的套接字的句柄(即,有等待读取的字节并且已被对等方关闭)。
  • The reactor dispatches this notification to the common TCP implementation.
  • TCP实现从套接字读取可用字节。有一些,它们被交付给应用程序代码。
  • 控制权返回到 react 堆, react 堆最终再次调用MsgWaitForMultipleObjects
  • MsgWaitForMultipleObjects再也不会指示该句柄处于事件状态。 TCP实现永远不会再次查看套接字,因此它永远不会检测到连接已关闭。

  • 这使得MsgWaitForMultipleObjects似乎是一种边缘触发的通知机制。 MSDN documentation说:
    Waits until one or all of the specified objects are in the signaled state
    or the time-out interval elapses.
    

    这听起来不像是边缘触发。听起来像是在触发电平。
    MsgWaitForMultipleObjects实际上是边缘触发的吗?还是它触发了级别,并且这种不当行为是由其行为的其他方面引起的?

    附录The MSDN docs for WSAEventSelect进一步解释了这里发生的事情,包括指出FD_CLOSE本质上是一次性事件。发出信号一次后,您将再也无法获得它。这有助于解释为什么Twisted存在此问题。不过,在有此限制的情况下,我仍然很想听听如何有效地使用MsgWaitForMultipleObjects

    最佳答案

    为了使用WSAEventSelect和区分事件,您需要调用WSAEnumNetworkEvents。确保您正在处理报告的每个事件,而不仅仅是第一个。
    WSAAsyncSelect易于确定原因,通常与MsgWaitForMultipleObjects一起使用。

    因此,您可以使用WSAAsyncSelect而不是WSAEventSelect

    另外,我认为您对边缘触发和电平触发之间的区别有基本的误解。您的推理似乎与自动重置与手动重置事件更相关。

    09-16 06:54