在Windows上,WSASend与WSAENOBUFS一起失败
在Windows XP上,当我在非阻塞套接字上的迭代中调用WSASend时,WSAENOBUFS失败 我这里有两个案例: 案例1: 在非阻塞套接字上,我调用WSASend。以下是伪代码:在Windows上,WSASend与WSAENOBUFS一起失败,windows,sockets,networking,tcp,Windows,Sockets,Networking,Tcp,在Windows XP上,当我在非阻塞套接字上的迭代中调用WSASend时,WSAENOBUFS失败 我这里有两个案例: 案例1: 在非阻塞套接字上,我调用WSASend。以下是伪代码: while(1) { result = WSASend(...); // Buffersize 1024 bytes if (result == -1) { if (WSAGetLastError() == WSAENOBUFS) {
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:
为了解决这个问题,我引用了,正如这里所建议的,
就在上面的代码之前,我用SO_SNDBUF调用了setsockopt并将buffersize设置为0(零)
在本例中,WSASend成功返回约2600次。然后它失败了。但在等待2600次之后,它再次成功,然后失败
现在我在这两种情况下都有这些问题:
案例1:
对于异步套接字(在Windows XP上),其行为更为奇怪。如果我忽略WSAENOBUFS并继续进一步写入套接字,我最终会断开WSAECONNRESET。目前还不确定为什么会发生这种情况?这些值没有记录,取决于您的计算机上安装了什么,而这些计算机可能位于应用程序和网络驱动程序之间。它们可能与机器中的内存量有关。Vista及以上版本的限制(最可能是非分页池内存和i/o页锁定限制)可能要高得多 处理此问题的最佳方法是将应用程序级流控制添加到协议中,这样您就不会假设您可以按自己喜欢的速率发送。有关非阻塞和异步I/O如何导致资源使用膨胀的详细信息,以及除非您有自己的流控制,否则您如何无法控制资源使用膨胀的详细信息,请参阅
总之,永远不要假设您可以使用非阻塞/异步API以您喜欢的速度将数据写入到线路中。请记住,由于TCP/IP的内部流控制的工作方式,您可能会使用无法控制的本地机器资源,而客户端是唯一能够控制这些资源释放回服务器机器上的O/s的速度的设备。这些值未记录,取决于您机器上安装的内容这可能位于应用程序和网络驱动程序之间。它们可能与机器中的内存量有关。Vista及以上版本的限制(最可能是非分页池内存和i/o页锁定限制)可能要高得多 处理此问题的最佳方法是将应用程序级流控制添加到协议中,这样您就不会假设您可以按自己喜欢的速率发送。有关非阻塞和异步I/O如何导致资源使用膨胀的详细信息,以及除非您有自己的流控制,否则您如何无法控制资源使用膨胀的详细信息,请参阅
总之,永远不要假设您可以使用非阻塞/异步API以您喜欢的速度将数据写入到线路中。请记住,由于TCP/IP内部流量控制的工作方式,您可能会使用无法控制的本地机器资源,而客户端是唯一能够控制这些资源释放回服务器机器上的O/s的速度的设备。对此,您无法得到答案,这些是tcp/ip驱动程序堆栈的未记录的实现细节。还有大量涉及的其他代码:病毒扫描程序、防火墙、代理、路由器、连接到的任何机器及其运行的软件。无法记录的细节。嗯,我所要寻找的是处理WSAENOBUFS错误的最佳方法。可能我需要更改一些配置,以避免出现此错误(或者至少不会经常出现此错误)。使用阻塞套接字显然是一种解决方法。只有当您有其他事情要做时,非阻塞才有意思。在这种情况下,您通常使用重叠的I/O,而非阻塞套接字在更简单的时候很有趣。向套接字写入字节的速率总是大大超过它们的发送速率,尤其是在人工测试程序中。错误代码最终会被清除,但当还有88兆字节要发送时,很容易等待的时间不够长。另一个原因是不在电线的另一端读取它们。@Andrew你为什么要使用非阻塞插座?你不能直接切换到异步IO吗?这基本上是具有多个连接的服务器的标准模型。如果你没有什么联系,就去同步。@usr:这是一个有趣而有用的建议。我发现异步IO的另一个奇怪行为。请看我的编辑。您无法得到答案,这些是tcp/ip驱动程序堆栈的未记录的实现细节。还有大量涉及的其他代码:病毒扫描程序、防火墙、代理、路由器、连接到的任何机器及其运行的软件。无法记录的细节。嗯,我所要寻找的是处理WSAENOBUFS错误的最佳方法。可能我需要更改一些配置,以避免出现此错误(或者至少不会经常出现此错误)。使用阻塞套接字显然是一种解决方法。只有当您有其他事情要做时,非阻塞才有意思。在这种情况下,您通常使用重叠的I/O,而非阻塞套接字在更简单的时候很有趣。向套接字写入字节的速率总是大大超过它们的发送速率,尤其是在人工测试程序中。错误代码最终会被清除,但很容易被删除