Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

can I read exactly one UDP packet off a socket?

Tags:

c

udp

Using UNIX socket APIs on Linux, is there any way to guarantee that I read one UDP packet, and only one UDP packet? I'm currently reading packets off a non-blocking socket using recvmsg, with a buffer size a little larger than the MTU of our internal network. This should ensure that I can always receive the full UDP packet, but I'm not sure I can guarantee that I'll never receive more than one packet per recvmsg call, if the packets are small.

The recvmsg man pages reference the MSG_WAITALL option, which attempts to wait until the buffer is filled. We're not using this, so does that imply that recvmsg will always return after one datagram is read? Is there any way to guarantee this?

Ideally I'd like a cross-UNIX solution, but if that doesn't exist is there something Linux specific?

like image 541
Brian Palmer Avatar asked Mar 30 '10 18:03

Brian Palmer


People also ask

Can UDP packets be split?

UDP is a datagram service. Datagrams may be split for transport, but they will be reassembled before being passed up to the application layer.

What happens if a single UDP packet is lost during?

In certain variants of TCP, if a transmitted packet is lost, it will be re-sent along with every packet that had already been sent after it. Protocols such as User Datagram Protocol (UDP) provide no recovery for lost packets.

How big should UDP packets be?

A UDP datagram is carried in a single IP packet and is hence limited to a maximum payload of 65,507 bytes for IPv4 and 65,527 bytes for IPv6.

Can UDP send and receive on same socket?

TCP vs UDP Once connected, a TCP socket can only send and receive to/from the remote machine. This means that you'll need one TCP socket for each client in your application. UDP is not connection-based, you can send and receive to/from anyone at any time with the same socket.


2 Answers

recvmsg will return you one packet, and it will be the entire packet (as long as the buffer you provide it is large enough).

From the POSIX documentation:

The recvmsg() function shall receive a message from a connection-mode or connectionless-mode socket.

"a message" means exactly one message (or packet), and,

For message-based sockets, such as SOCK_DGRAM and SOCK_SEQPACKET, the entire message shall be read in a single operation.

like image 165
James McNellis Avatar answered Sep 27 '22 23:09

James McNellis


The accepted answer doesn't clearly answer the OP's question, because it mentions buffer size only in passing.

I'm currently reading packets off a non-blocking socket using recvmsg, with a buffer size a little larger than the MTU of our internal network.

It's important for your buffer to be big enough to fit one entire datagram. A datagram can be up to 65,536 bytes. When a large datagram is fragmented because of MTU it will be reassembled by the stack, you won't know about this, you will just receive nothing until all the fragments are received and put back together into the original datagram. If you make your buffer slightly bigger than one MTU, for instance 1600 bytes, and you call recv() on an incoming datagram that is 40K bytes, you will get just the first 1600 bytes.

like image 22
MAXdB Avatar answered Sep 27 '22 23:09

MAXdB