4

Good Day,

I'm developing an application in VC++ that communicates using UDP protocol with winsock on Windows XP. Previously I've been able to assume that all packets being received by the tool were from a single target. However I'm now doing a broadcast receive. The listening thread has minimal overhead and should spend all of its time on the below line:

rv = recvfrom(socket, 
              p_buffer_p, 
              p_size,
              0,
              (sockaddr*)&clientService_in, //This is set to do a broadcast recv
              &SenderAddrSize);

My question is whether or not I can assume that a buffer that I get from a single return from recvfrom is from a single target. That is, does 1 call to send in the sending app equal 1 return from recvfrom in the receiving app? Or can multiple sends from multiple senders get mushed together into 1?

I'm assuming that a single send from a target can't get split up into multiple returns from recvfrom. I've always assumed this and never had a problem anyway.

One more thing, its a SOCK_DGRAM type of socket.

Ian
  • 4,169
  • 3
  • 37
  • 62

2 Answers2

6

No, a UDP message cannot be split. They arrive as they were sent. Also, multiple UDP messages are NOT concatenated.

So N sendto messages correspond to N recvfrom calls.

Quote from wiki:

Datagrams – Packets are sent individually and are checked for integrity only if they arrive. Packets have definite boundaries which are honored upon receipt, meaning a read operation at the receiver socket will yield an entire message as it was originally sent.

INS
  • 10,594
  • 7
  • 58
  • 89
  • Okay, thankyou. I had read something posted elsewhere that seemed to indicate that they could be split and mushed, but I suppose this was for a different protocol. I'm not familiar with the differences between connections in winsock yet. – Ian Jan 05 '12 at 20:08
  • @Ian That protocol was probably a stream based protocol (TCP/SCTP) – INS Jan 05 '12 at 20:10
2

You are correct that a single call to recvfrom() will return at most one UDP datagram. But there is no guarantee that each datagram will actually arrive.

In particular, if the UDP datagram that you send is too large, it can become split into pieces at the network level (fragmentation) which increases the likelihood that the datagram will be dropped (because the loss of any fragment causes the loss of the whole). You don't see fragmentation at the application level because the network level reassembles the packet for you.

Things can get very tricky because it is impossible to know in advance exactly how large is too large. There are various algorithms for finding out, but they all amount to trial and error. Worse, firewalls, routers, and operating systems can (and often do) change their behavior toward fragmented datagrams over time. There can be scenarios where a packet of a particular size or composition will always be dropped because it violates some firewall rule.

So never assume that a sendto() will necessarily result in a recvfrom(), and try to keep your datagrams small (less than 1400 bytes is fairly safe, less than 512 bytes is very safe).

Seth Noble
  • 3,233
  • 19
  • 31