在Windows上,WSASend失败并使用WSAENOBUFS

时间:2013-10-26 15:47:28

标签: windows sockets networking tcp

在Windows XP上,当我在非阻塞套接字上的迭代中调用 WSASend 时,它失败了WSAENOBUFS。

我在这里有两个案例:

案例1:

在非阻塞套接字上,我正在调用 WSASend 。这是伪代码:

while(1)
{
    result = WSASend(...); // Buffersize 1024 bytes
    if (result == -1)
    {
        if (WSAGetLastError() == WSAENOBUFS)
        {
            // Wait for some time before calling WSASend again
            Sleep(1000);
        }
    }
}

在这种情况下,WSASend成功返回大约88000次。然后它失败了WSAENOBUFS并且即使在代码中显示一段时间后尝试也永远不会恢复。

案例2:

为了解决这个问题,我提到了 this ,并按照其中的建议, 就在上面的代码之前,我用SO_SNDBUF调用 setsockopt 并设置buffersize 0(零)

在这种情况下,WSASend成功返回约2600次。然后就失败了。但等待它再次成功2600次然后失败。

现在我在这两种情况下都有这些问题:

案例1:

  1. 在这里决定这个数字是88000的因素是什么?
  2. 如果失败是因为TCP缓冲区已满,为什么它在一段时间后没有恢复?
  3. 案例2:

    1. 同样,哪些因素决定了2600这个数字?
    2. 正如Microsoft知识库文章中所述,如果不直接从应用程序缓冲区发送内部TCP缓冲区,为什么它会因WSAENOBUFS而失败?
    3. 编辑:

      对于异步套接字(在Windows XP上),行为更奇怪。如果我忽略WSAENOBUFS并继续写入套接字I,最终会断开连接WSAECONNRESET。目前还不确定为什么会发生这种情况?

1 个答案:

答案 0 :(得分:3)

值未记录,取决于您的计算机上可能位于应用程序和网络驱动程序之间的内容。它们可能与机器中的内存量有关。 Vista及以上版本的限制(很可能是非分页池内存和i / o页锁定限制)可能会高很多。

解决问题的最佳方法是在您的协议中添加应用程序级别的流量控制,这样您就不会认为只需发送您想要的任何速率。有关非阻塞和异步I / O如何导致资源使用情况以及除非您拥有自己的流控制之外无法控制资源使用情况的详细信息,请参阅this blog posting

总之,永远不要假设您可以使用非阻塞/异步API以尽可能快的速度将数据写入线路。请记住,由于TCP / IP的内部流量控制如何工作,您可能会使用无法控制的本地计算机资源,并且客户端是唯一可以控制这些资源在服务器上释放回O / S的速度的因素机。