recv() has no time to receive all the UDP packets

2019-06-03 15:35发布

I'm developing a network application for both Windows XP and Seven. The application receives data via UDP and uses blocking sockets, select (not WSAPoll) and recv functions.

For testing I'm using two identical notebooks with different OS installed: Dell Latitude D630, Core 2 Duo 2.2GHz, 4Gb RAM, Broadcom NetXtreme 57xx Gigabit Controller. I've got the following results:

Windows XP Professional 32bit: The network monitor application shows that the network interface receives data from LAN with average speed 35 MBytes/s. The application receives data from a socket with average speed 30 MBytes/s and detects 13% losses.

Windows 7 Enterprise 32bit: The network monitor application shows that the network interface receives data from LAN with average speed 35 MBytes/s. The application receives data from a socket with average speed 10 MBytes/s and detects 65% losses.

It looks like the application doesn't have enough time to receive all the packets from a socket on Windows 7. But why the result is different from Win XP?

1条回答
甜甜的少女心
2楼-- · 2019-06-03 16:04

I am providing the following for anyone who is dealing with this or similar problems as I came across this posting while dealing with something similar. I hope that this will save someone else some time.

I also want to thank @Roman R. for his comment above and @Rom098 for following up with a comment indicating that a change in buffer size helped him/her as well.

An application which uses Windows sockets with UDP in a low data rate to communicate data between several terminals was working fine with Windows XP but with a move to Windows 7 we began experiencing problems with network messages being dropped.

The architecture is that a client terminal has a conversation with a server terminal by sending and receiving a series of UDP messages with the client maintaining its own state. The client terminal has a thread, the Client Thread, which handle user input and the sending and receiving of messages to the server terminal. The server terminal has a thread, the Server Thread, which handles request messages from other terminals as well as its own Client Thread. The simple message sequence looks like:

  • client terminal sends a request message to a server terminal
  • server terminal responds with an acknowledgement message
  • server terminal processes request and sends a response message to client
  • client terminal sends an acknowledgement to server terminal

Looking at the comments above, we checked using a debugger and found that Windows 7 has a default WinSock receive and send buffer size of 8K (8192 bytes). Looking about on the internet, it appears that Windows XP had a higher processing rate for network traffic.

We have made two changes in our network layer that handle the communication.

The first is to use the setsockopt() function to double the size of the receive and send buffers using the following code.

iOptLen = sizeof(INT);
error = getsockopt (iSocket, SOL_SOCKET, SO_RCVBUF, (PCHAR)(&iOpt), &iOptLen);
if (error < 0) {
    error = WSAGetLastError();
} else if (iOpt < 1024 * 16) {
    iOpt = 1024 * 16;
    error = setsockopt(iSocket, SOL_SOCKET, SO_RCVBUF, (const PCHAR)(&iOpt), sizeof(iOpt));
    if (error < 0) {
        error = WSAGetLastError();
    }
}
iOptLen = sizeof(INT);
error = getsockopt (iSocket, SOL_SOCKET, SO_SNDBUF, (PCHAR)(&iOpt), &iOptLen);
if (error < 0) {
    error = WSAGetLastError();
} else if (iOpt < 1024 * 16) {
    iOpt = 1024 * 16;
    error = setsockopt(iSocket, SOL_SOCKET, SO_SNDBUF, (const PCHAR)(&iOpt), sizeof(iOpt));
    if (error < 0) {
        error = WSAGetLastError();
    }
}

The second change we made is if the Client Thread is waiting for an acknowledgement and the response message comes in from the server terminal then process the response message as a combination of acknowledgement and response. What we are doing is assuming that the acknowledgement message was dropped at some point.

With these two changes the lag is no longer noticeable though our measurements indicate that sometimes the acknowledgement message from server terminal to client terminal is still being dropped.

See also

Change default socket buffer size under Windows which uses a Windows Registry change to modify the default buffer size from 8K to something else.

What is the size of a socket send buffer in Windows? which is about TCP however provides additional information about setsockopt().

Winsock UDP packets being dropped? which discusses a similar problem with a number of answers providing additional information.

Application Note: Windows 2000/XP TCP Tuning for High Bandwidth Networks from Innominate.com has some interesting information though perhaps a bit dated as I understand that with Windows 7 the network layers were rewritten.

Real time communications over UDP protocol from Michael Pan on codeproject.com has quite a bit of details about the technical issues with using UDP.

查看更多
登录 后发表回答