Atul
Atul

Reputation: 4320

On Windows, WSASend fails with WSAENOBUFS

On Windows XP when I am calling WSASend in iterations on non-blocking socket, it fails with WSAENOBUFS.

I've two cases here:

Case 1:

On non-blocking socket I am calling WSASend. Here is pseudo-code:

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

In this case WSASend returns sucessfully for around 88000 times. Then it fails with WSAENOBUFS and never recovers even when tried after some time as shown in the code.

Case 2:

In order to solve this problem, I referred this and as suggested there, just before above code, I called setsockopt with SO_SNDBUF and set buffersize 0 (zero)

In this case, WSASend returns sucessfully for around 2600 times. Then it fails. But after waiting it succeeds again for 2600 times then fails.

Now I've these questions in both the cases:

Case 1:

  1. What factors decides this number 88000 here?
  2. If the failure was because of TCP buffer was full, why it didn't recover after some time?

Case 2:

  1. Again, what factors decides the number 2600 here?
  2. As given in Microsoft KB article, if instead of internal TCP buffers it sends from application buffer directly, why would it fail with WSAENOBUFS?

EDIT:

In case of asynchronous sockets (On Windows XP), the behavior is more strange. If I ignore WSAENOBUFS and continued further writing to socket I eventually get disconnection WSAECONNRESET. And not sure at the moment why does that happen?

Upvotes: 3

Views: 3405

Answers (1)

Len Holgate
Len Holgate

Reputation: 21616

The values are undocumented and depend on what's installed on your machine that may sit between your application and the network driver. They're likely linked to the amount of memory in the machine. The limits (most probably non-paged pool memory and i/o page lock limit) are likely MUCH higher on Vista and above.

The best way to deal with the problem is add application level flow control to your protocol so that you don't assume that you can just send at whatever rate you feel like. See this blog posting for details of how non-blocking and async I/O can cause resource usage to balloon and how you have no control over it unless you have your own flow control.

In summary, never assume that you can just write data to the wire as fast as you like using non-blocking/async APIs. Remember that due to how TCP/IP's internal flow control works you COULD be using an uncontrollable amount of local machine resources and the client is the only thing that has any control over how fast those resources are released back to the O/S on the server machine.

Upvotes: 5

Related Questions