The first UDP message to a specific remote ip is lost

I am working on a solution based on a local network with a “server” that needs to manage several “players”. My protocol of choice is UDP, because it is easy, I do not need connections, my traffic consists of short commands from time to time, and I want to use a combination of broadcast messages for synchronization and single target messages for individual player commands.

Multicast TCP would be an alternative, but more complex, not quite suitable for the task, and often not supported by the hardware.

Unfortunately, I have a strange problem:

The first datagram that is sent to a specific ip using sendto is lost. Any datagram sent a short time after that to the same ip is received. But if I wait a while (a few minutes), the first "sendto" will be lost again.

Broadcast datagrams always work. Local sendings (to the same computer) always work.

I assume that the operating system or router / switch has some translation table from IP to MAC addresses, which are forgotten when they are not used for several minutes, and that, unfortunately, leads to the loss of datagrams. I could observe this behavior with other equipment of the router / switch, so my suspect is a Windows network layer.

I know that UDP is by definition “unreliable,” but I can't believe it is so far that even if the physical connection works and everything is well-defined, packets can get lost. Then it will be literally useless.

Technically, I open the UDP socket, bind it to the port and INADRR_ANY. Then I use "sendto" and "recvfrom". I never connect - I do not want, because I have several players. As far as I know, UDP should work without a connection.

My current workaround is that I regularly send fictitious datagrams to all specific ips players - this solves the problem, but it’s somehow “unsatisfactory”

Question: Does anyone know this problem? Where is it from? How can I solve it?

Edit:

I threw it back to the following test program:

int _tmain(int argc, _TCHAR* argv[]) { WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); SOCKET Sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); SOCKADDR_IN Local = {0}; Local.sin_family = AF_INET; Local.sin_addr.S_un.S_addr = htonl(INADDR_ANY); Local.sin_port = htons(1234); bind(Sock, (SOCKADDR*)&Local, sizeof(Local)); printf("Press any key to send...\n"); int Ret, i = 0; char Buf[4096]; SOCKADDR_IN Remote = {0}; Remote.sin_family = AF_INET; Remote.sin_addr.S_un.S_addr = inet_addr("192.168.1.12"); // Replace this with a valid LAN IP which is not the hosts one Remote.sin_port = htons(1235); while(true) { _getch(); sprintf(Buf, "ping %d", ++i); printf("Multiple sending \"%s\"\n", Buf); // Ret = connect(Sock, (SOCKADDR*)&Remote, sizeof(Remote)); // if (Ret == SOCKET_ERROR) printf("Connect Error!\n", Buf); Ret = sendto(Sock, Buf, strlen(Buf), 0, (SOCKADDR*)&Remote, sizeof(Remote)); if (Ret != strlen(Buf)) printf("Send Error!\n", Buf); Ret = sendto(Sock, Buf, strlen(Buf), 0, (SOCKADDR*)&Remote, sizeof(Remote)); if (Ret != strlen(Buf)) printf("Send Error!\n", Buf); Ret = sendto(Sock, Buf, strlen(Buf), 0, (SOCKADDR*)&Remote, sizeof(Remote)); if (Ret != strlen(Buf)) printf("Send Error!\n", Buf); } return 0; 

The program opens the UDP Socket and sends 3 datagrams per line for each keystroke to a specific IP address. Start the proxy server, watching your UDP traffic, press the key, wait a while and press the key again. You do not need a receiver at the remote IP address, it does not matter, except that you do not receive black marked "inaccessible" packets. This is what you get:

Wireshark snapshot

As you can see, the first dispatch initiated an ARP lookup for the IP address. While this search was waiting, the first 2 of three consecutive shipments were lost. The second keystroke (after completing the IP search) sent 3 messages correctly. Now you can retry sending messages and it will work until you wait (in about a minute, until the transfer of the addressee is lost again), and you will see the drop-out again.

This means: when sending UDP messages, there is no send buffer and ARP requests are expected! All messages are lost except the last. Also, "sendto" is not blocked until it is successfully delivered, and there is no error return!

Well, it surprises me and makes me a little sad, because it means I need to live with my current workaround or implement an ACK system that sends only one message and then waits for an answer - which will not be easier and mean a lot difficulties.

+7
source share
4 answers

I post this long after others reply, but it is directly related.

Winsock packs UDP packets if there is no ARP entry for the destination address (or gateway for the destination).

Thus, it is likely that some first UDP packet fell because there was no ARP record at that time - and unlike most other operating systems, winsock only puts 1 packet until the ARP request completes.

This is documented here :

ARP queues only one outgoing IP datagram for the specified destination, as long as this IP address is resolved for the MAC address. If a UDP-based application sends multiple IP datagrams to the same destination without any gaps between them, some of the datagrams can be deleted if there is no ARP cache entry already. An application can compensate for this by calling the Iphlpapi.dll SendArp () procedure to set an ARP cache entry before sending a packet stream.

The same behavior can be seen on Mac OS X and FreeBSD :

When an interface requests a mapping for an address, rather than in a cache, ARP queues a message that requires the display and translation of a message on its associated network, requesting a mapping of addresses. If the response is provided that the new mapping is cached and any pending message is sent. ARP will queue no more than one packet, waiting to respond to a mapping request; only the most recently `` transmitted '' packet is saved.

+12
source

It is assumed that UDP packets are buffered upon receipt, but the UDP packet (or its Ethernet frame) can be dropped at several points on a given machine:

  • the network card does not have enough space to accept it,
  • The OS network stack does not have enough buffer memory to copy,
  • match the firewall / packet filtering filtering pattern,
  • the application does not listen on the IP address and destination port,
  • The socket receive buffer for listening is full.

The first two points concern too much traffic, which is hardly the case here. Then I hope that point 4. is not applicable, and your software expects data. Section 5. The point is that your application does not process network data fast enough - it also does not look like this.

Translation between MAC and IP addresses is done through the Address Resolution Protocol . This does not cause packet failure if your network is configured correctly.

I would turn off the Windows firewall and any antivirus / deep package checking software and check that there is wireshark on the phone. This will most likely point you in the right direction - if you can sniff these first packets on “sent” machines, then check the local configuration (firewall, etc.); if you do not, check your network - something in the way is interfering with your traffic.

Hope this helps.

+4
source

erm ..... His computer makes an ARP request. When you first start sending, your com does not know the address of the recipient, so it cannot send any packets. It uses the recipient IP address to execute an ARP request to obtain the mac address. During this process, any udp packets you are trying to send cannot be sent because the destination MAC address is not yet known.

Once your com gets the mac address, it can start sending. However, the mac address will only remain in your ARP cache for 2 minutes (if no further action is found between you and the recipient) or 10 minutes (completely cleared from the ARP cache, even if the connection is active). This is why you experience this problem every few minutes.

+1
source

Does anyone know this problem?

The real problem is that you assumed that sending UDP packets is reliable. This is not true.

The fact that you lost the first packet with your current network configuration is indeed a minor issue. You may be able to fix this, but at any time you are still vulnerable to packet loss.

If packet loss is a problem for you, you really should use TCP. You can create a reliable protocol in UDP, but if you do not have a good reason for this, it is not recommended.

-2
source

All Articles