Is the data intact when sent over UDP?

From wikipedia, If the data is larger then MTU, The actual data is sent in multiple IP fragmented frames. If a fragment is lost, the entire UDP frame is considered lost, which ensures that the data is reassembled intact.

But UdpSocket::send_to returns the number of bytes written.

Does this mean that the complete data is not guaranteed to be sent in single UDP frame ? Rather the data is partially sent ?

Does this mean that the complete data is not guaranteed to be sent in single UDP frame ?

Yes.

You shouldn't assume how many frames your data is split into, because this often changes depending on networking configuration. For example, a VPN will have a lower MTU than the typical 1500.

I assume the Rust function corresponds to the sendto function on Linux (and equivalent on windows) for which I can find no documentation indicating a return value not equal to either -1 or the length is possible.

Let's say, MTU is 4096+,
So if I send 4096 bytes, there might be less number of bytes written ?

Also from wikipadia, if MTU less then actual data, It signal with Datagram Too Big Error.
See more

Just try sending 65507+ bytes in ipv4 loopback address you will get an error from send_to(), It doesn't return Number of bytes written.

I am really confused.

Are you sure you really need to use the low-level socket api for your program? Using low level networking APIs without knowing it well and some experience is hard.

To answer your question:

So if I send 4096 bytes, there might be less number of bytes written ?

No, I don't think so. On success, it will return the number of bytes written (which is all of them), else an error.

Also from wikipadia, if MTU less then actual data, It signal with Datagram Too Big Error.

This might be due to the socket being configured for the messages to be sent atomically. From sendto(2):

       EMSGSIZE
              The socket type requires that message be sent atomically, and the size of
              the message to be sent made this impossible.

Also, if the don't fragment flag is set, and your MTU is big enough, that doesn't mean everyone else's in the path is as well. So despite your NIC having a big enough MTU you might still get ICMP 4 (frame too big) because the frame needs to be split up to fit into someone else's MTU along the path.

Again, getting low level networking right is hard, and if you don't really have to, don't. Use higher level protocols.

So returned number from send_to() is always equal to actual data ?

To the best of my knowledge, if the send operation was successful, yes.

Then it should return Result<()>, just like write_all() :face_with_diagonal_mouth:

I guess this was done to reflect what Linux sendto() does

Written to the socket, sure. But it's the internet; there's no guarantee that it'll ever get to the other end, and it's UDP so it won't even ask for acknowledgement (let alone retry).

You almost certainly don't want to use raw UDP. Use something like QUIC - Wikipedia instead.

1 Like

It's a network, there's no guarantee even locally.[1]


  1. My life would be easier if all my coworkers understood this... ↩ī¸Ž

2 Likes

The number of bytes written (sent) is not guaranteed to be the same as the number of bytes received. With UDP you have no guarantees about anything. It's like shouting into the Internet.