UDP API in rust

1) The API to send here returns a Result<usize> . Why is this? In my head, UDP transmission is all or nothing. The return value seems to suggest that the sending may be successful, but the whole data cannot be written, which makes me code as follows:

 let mut bytes_written = 0; while bytes_written < data.len() { bytes_written += match udp_socket.send_to(&data[bytes_written..]) { Ok(bytes_tx) => bytes_tx, Err(_) => break, } } 

Recently, someone told me that this is completely unnecessary. But I do not understand. If so, then why does Result<()> return instead, what did I expect?

2) For reading , although I understand. I could give it a buffer of 100 bytes in size, but the datagram can be only 50 bytes long. So essentially I should use only read_buf[..size_read] . Here my question is, what happens if the buffer size is 100 and the datagram size is 150 bytes? Will recv_from fill only 100 bytes and return Ok(100, some_peer_addr) ? If I re-read, will it populate the remaining datagram? What if another 50 byte datagram arrived before my second read? Will I only get the remaining 50 bytes a second time and 50 bytes of a new datagram for the 3rd time, or the full 100 bytes a second time, which also contains a new datagram? Or will there be a mistake, and I will lose the first datagram in my initial reading and never be able to restore it?

+7
udp networking rust
source share
2 answers

The answer to both of these questions is to document the corresponding functions of the BSD, sendto() and recvfrom() sockets. If you are using some * nix system (e.g. OS X or Linux), you can use man sendto and man recvfrom to find it.

1) sendto() man page is rather vague; Windows The API page explicitly states that the return value may be less than the len argument. See also this question. It seems that this particular point is somewhat documented. I think that it is probably safe to assume that the return value will always be either len or an error code. Problems can arise if the length of the data sent via sendto() exceeds the internal buffer size inside the OS kernel, but it seems that at least Windows will return an error in this case.

2) recvfrom() explicitly states that part of the datagram that does not fit in the buffer will be discarded:

The recvfrom () function returns the length of the message written to the buffer pointed to by the buffer argument. For message-based sockets, such as SOCK_RAW, SOCK_DGRAM, and SOCK_SEQPACKET, the entire message must be read in one operation. If the message is too long to be inserted into the supplied buffer and MSG_PEEK is not specified in the flags argument, the excess bytes should be discarded.

So yes, recv_from() fill exactly 100 bytes, the rest will be discarded, and further calls to recv_from() will return new datagrams.

+9
source share

If you dig it , it just wraps the C sendto function . This function returns the number of bytes sent, so Rust simply passes this value (when handling the -1 case and turning errno into actual errors).

+2
source share

All Articles