【问题标题】:How network event FD_WRITE is generated when using Event Driven Sockets?使用事件驱动套接字时如何生成网络事件 FD_WRITE?
【发布时间】:2013-05-10 09:28:22
【问题描述】:

我正在开发基于 newtwork 事件的套接字应用程序。

当客户端已经发送了一些数据并且在套接字上有要读取的内容时,会产生 FD_READ 网络事件。

现在根据我的理解,当服务器要通过套接字写入时,必须有一个事件产生,即FD_WRITE。但是这个消息是怎么产生的呢?

当有可读取的内容时,FD_READ 会自动生成,但是当服务器要写入内容时,FD_WRITE 呢?

谁能帮我解决这个困惑?

下面是sn-p的代码:

WSAEVENT hEvent = WSACreateEvent();
WSANETWORKEVENTS events;
WSAEventSelect(newSocketIdentifier, hEvent, FD_READ | FD_WRITE);

   while(1)
      {   //while(1) starts
         waitRet = WSAWaitForMultipleEvents(1, &hEvent, FALSE, WSA_INFINITE, FALSE);
         //WSAResetEvent(hEvent);
         if(WSAEnumNetworkEvents(newSocketIdentifier,hEvent,&events) == SOCKET_ERROR)
            {
              //Failure
            }
     else
        {   //else event occurred starts
            if(events.lNetworkEvents & FD_READ)
            {
                            //recvfrom()   
            }
            if(events.lNetworkEvents & FD_WRITE)
            {
                 //sendto()
            }
        }
      }

【问题讨论】:

    标签: c windows winapi events network-programming


    【解决方案1】:

    FD_WRITE 表示您现在可以写入套接字。如果发送缓冲区已满(您发送数据的速度比在网络上发送的速度要快),最终您将无法再写入,直到您稍等片刻。

    一旦由于缓冲区已满而导致写入失败,系统会向您发送此消息,让您知道您可以重试该发送。

    当你第一次打开套接字时也会发送它,让你知道它在那里,你可以开始写了。

    http://msdn.microsoft.com/en-us/library/windows/desktop/ms741576(v=vs.85).aspx

    FD_WRITE 网络事件的处理方式略有不同。一个 首次连接套接字时记录 FD_WRITE 网络事件 致电connectConnectExWSAConnectWSAConnectByList, 或WSAConnectByName 函数或当使用accept 接受套接字时, AcceptExWSAAccept 函数,然后在发送失败后 WSAEWOULDBLOCK 和缓冲区空间变得可用。因此,一个 应用程序可以假设从第一个开始就可以发送 FD_WRITE 网络事件设置并持续到发送返回 WSAEWOULBLOCK。在这样的失败之后,应用程序会发现 当 FD_WRITE 网络事件发生时,再次发送是可能的 记录并设置关联的事件对象。

    因此,理想情况下,您现在可能会保留是否可以写作的标志。它开始时为 true,但最终,在调用 sendto 时会得到一个 WSAEWOULDBLOCK,并将其设置为 false。收到 FD_WRITE 后,将标志设置回 true 并继续发送数据包。

    【讨论】:

    • 感谢您的解释,但我使用的是没有 coonect() 和 accept() 的 udp 套接字 :(
    • 您仍在调用 sendto。这会导致缓冲区被填满。在它们填满,然后在一定程度上清空后,您将收到此事件 - 请参阅我粘贴的段落的这一部分:发送失败并显示 WSAEWOULDBLOCK 并且缓冲区空间可用
    • 我有一些想法,但我仍有困惑。当我在它之前调用 sendto() 时,FD_SEND 的原因是什么?你能分享一个如何使用FD_WRITE的简单例子
    • 你不“使用它”..它只是告诉你在套接字已满之前,但它不再是了,所以你可能会调用 sendto 并且它不会发送给你返回一个错误(WSAEWOULDBLOCK)。好吧,您可以完全忽略它,但是当它无法成功时,您可能会浪费大量时间调用 sendto。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多