Reputation: 316
I have quite standard setup of my udp receiver socket. My sender sends data at 36Hz and receiver reads at 72Hz. 12072bytes per send.
When I do cat /proc/net/udp. I get usually
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops
7017: 0101007F:0035 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 10636 2 0000000000000000 0
7032: 00000000:0044 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 14671 2 0000000000000000 0
7595: 00000000:0277 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 11113 2 0000000000000000 0
7660: 00000000:22B8 00000000:0000 07 00000000:00004100 00:00000000 00000000 1000 0 251331 3 0000000000000000 352743
You can see the rx_queue has some values in there, reads not fast enough ?
My code
int recv_len = recvfrom(s, buf, BUFLEN, MSG_TRUNC, (struct sockaddr *) &si_other, &slen);
// dont worry buflen is like 64000 no error here
std::cout <<" recv_len "<<recv_len<<std::endl;
I always get output as recv_len 12072 even though the queue is quite big ? why is this ? Is there a way to speed up my read or read all the messages in the queue ? I dont understand what's wrong even my read frequency is higher.
Upvotes: 0
Views: 439
Reputation: 12337
UDP datagrams always travel as a complete atomic unit. If you send a 12072 byte UDP datagram, your receiver will get exactly one 12072 byte datagram or nothing at all -- you won't ever receive a partial message (*) or multiple messages concatenated.
Note that with datagrams of this size, they're almost certainly being fragmented at the IP layer because they're probably larger than your network's MTU (maximum transmission unit). In that case, if any one of the fragments is dropped along the way or at the receiving host or found to be corrupted, the entire UDP datagram will be dropped.
(* A message may be truncated if the buffer provided to recvfrom
is too small, but it will never even be considered for receiving if the entire message could not be reassembled in the kernel.)
If you are unable to receive all the messages being sent, I would check whether you need to increase the kernel buffer space allocated to UDP. This is done with the sysctl
utility. Specifically you should check and possibly adjust the values of net.core.rmem_max
and net.ipv4.udp_mem
. See the corresponding documentation:
https://www.kernel.org/doc/Documentation/sysctl/net.txt
https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
Finally, it seems a bit curious to talk about "read frequency" -- I assume that means you are polling the socket 72 times per second? Why not just dedicate a thread to reading from the socket. Then the thread can block on the recvfrom
and the receive will complete with the least possible latency. (In any case, this is worth a try, even if only for a test -- to see if the polling is contributing to your inability to keep up with the sender.)
Upvotes: 3