-1

Could anyone please help me on improving the performance of a udp receiver. I am only able to get 1Mb/s but need to enhance the performance to almost 5Mb/s. There are also missing of Logs because the receiver is not able to receive all the messages due to this less performance. Is there any tips on how we could we increase the performance. I am using socket calls to get the data packets.

#define MAX_PACKET_SIZE 65535
#define UPD_DATAGRAM_BUFFER_SIZE 1536
m_nSocket = socket(AF_INET, SOCK_DGRAM, 0);
/* Set socket buffer size */
    int buffer_size = m_nBufferSize;
    ret = setsockopt(m_nSocket, SOL_SOCKET, SO_RCVBUF, (char*) &buffer_size, sizeof(buffer_size));
    ret = setsockopt(m_nSocket6, SOL_SOCKET, SO_RCVBUF, (char*) &buffer_size, sizeof(buffer_size));
/* Set socket timeout */
#if defined (WIN32) || defined (WIN64)
    int timeout = m_nTimeout;
    ret = setsockopt(m_nSocket, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(timeout));
    ret = setsockopt(m_nSocket6, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(timeout));
#else
    struct timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = m_nTimeout * 1000; //must be in microseconds
    ret = setsockopt(m_nSocket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
    ret = setsockopt(m_nSocket6, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
#endif
//bind
    m_address.sin_family = AF_INET;
    m_address.sin_addr.s_addr = htonl(INADDR_ANY);
    m_address.sin_port = htons(m_nPort);
    ret = bind(m_nSocket, (struct sockaddr*) &m_address, sizeof(m_address));
//receive data
recvfrom(m_nSocket, m_sBuffer, UPD_DATAGRAM_BUFFER_SIZE, 0, (struct sockaddr*) &m_address, &server_length);

Does increase in buffer size increase udp performance? What else could we do to increase udp performance?

  • do we need to increase the receive buffer size and receive timeout values – Joseph Babu Onasseril Apr 19 '18 at 05:44
  • You should certainly set the receive buffer size as high as you can. The receive timeout value does not affect performance. But UDP datagram loss can occur anywhere in the network, not just at the receiver because it is slow. NB don't use comments to improve your question. Improve your question. In the question. – user207421 Apr 19 '18 at 05:46
  • What is `MAX_PACKET_SIZE` for? If it's the maximum UDP payload, it's too large. If it's the receive buffer size, it's too small. And what is the value of `m_nBufferSize`? – user207421 Apr 19 '18 at 06:17
  • You seem to be missing lots of `#` before your preprocessor conditions. – Barmar Apr 19 '18 at 06:24
  • @EJP : MAX_PACKET_SIZE is mentioned in the following link: https://stackoverflow.com/questions/42609561/udp-maximum-packet-size m_nBufferSize is the value we are giving as receiver buffer size. In our case we are giving as 1,048,576 bytes which is 1Mb – Joseph Babu Onasseril Apr 19 '18 at 06:35
  • does increasing receive buffer size would increase the rate at which the udp receiver receives the data packets? – Joseph Babu Onasseril Apr 19 '18 at 06:52
  • 1. The question you cite, and the answer, both state clearly that the maximum UDP payload is 65507 bytes, but this is hopelessly impractical in practice. And you don't need a `#define` for a fundamental constant of IP. It isn't a number you are actually concerned with. 2. I can see for myself what you're using `m_nBufferSize` for. I asked you what its value is. You haven't answered that. 3. No, but it reduces the possibility of the datagram being discarded at the receiving host due to the receive buffer being full. – user207421 Apr 19 '18 at 07:17
  • So use another thread to process the data - that way your recv will be called faster. – UKMonkey Apr 19 '18 at 08:06
  • @UKMonkey : Processing of data is used in an another thread where as data is received (using recv) in a different thread – Joseph Babu Onasseril Apr 19 '18 at 09:05
  • @EJP: m_nBufferSize = 1,048,576 bytes (1 Mb) – Joseph Babu Onasseril Apr 19 '18 at 09:07
  • @EJP: what is the maximum buffer size that could be given on a recv() call? In my case I have given: UPD_DATAGRAM_BUFFER_SIZE 1536. Is this correct? – Joseph Babu Onasseril Apr 19 '18 at 10:25

1 Answers1

2

Increasing the RCVBUF size will not make it faster but more reliable. If the RCVBUF is full, next incoming packets are dropped.

Details:

A recvfrom() call receives exactly one UDP packet which has - for IPv4 - a maximum size of 65535 bytes. UDP packets may be split into fragments, but this is hidden from the user.

If your sendto() call sends more bytes than a single recvfrom() receive buffer accepts, the remaining data will be dropped.

The SO_RCVBUF is accepting packets while no recvfrom() call is running. If you call recvfrom() it checks for a packet in the RCVBUF and only blocks and waits for a new packet if the receive buffer is empty.

If you have a sender sending huge amounts of data for example within a for loop, then it is likely you loose some data if your RCVBUF is not large enough and your recvfrom() calls are not fast enough (i.e. when processing packets between revfrom() calls).

UDP is not made for burst transfers. It even does not guarantee the delivery of a packet and the packet receive order may differ from the send order.

Maybe you should use TCP/IP ?


If you try to implement your own UDP based stream communication you could do the following:

1) Send UDP packets with a maximum size of about 1400 Bytes.

2) Add a 32 or 64-Bit Header to your UDP packets containing the stream offset where this packet belongs to (i.e. the first 1400 byte packet has a stream offset of 0 and the second one has an offset of 1400, the third one 2800 and so on)

3) The client allocates a buffer huge enough to store the whole transmission. Every packet is copied into this buffer at the location specified within the first 32 or 64 bit of the packet. (This sorts your packet)

4) The server sends only loads of - for example - 10 MiB and the client requests more data while it reads from the RCVBUF (using recvfrom()). So the server does not fill the RCVBUF and no packets are being dropped by the receiving machine. For maximum performance the client should request the next load while still receiving data from the previous load. (This makes sure the receive buffer does not overflow)

5) The client request the retransmission of any missing packets (this can be combined with the request in step 4) (This makes sure the transmission is complete and no packets are lost)

Why only 1400 bytes? Because you don't want to fragment your packets on high speed networks. (On fast networks the 16-bit packet-id can overflow within the reassembly timeframe and - if the checksum matches or is not set - fragments of different packets could be reassembled. Took me hours to find out why)

Andreas H.
  • 1,757
  • 12
  • 24
  • Suppose the sender is sending a data at a higher rate (e.g 5Mb/s) and the receiver is only receiving data packets (e.g 1Mb/s), what should I do to get the data at 5 Mb/s that sender sends. Does increasing RCVBUF size to 5 Mb increases the data rate at receiver side – Joseph Babu Onasseril Apr 19 '18 at 09:19
  • what is the maximum buffer size that could be given on a recv() call? – Joseph Babu Onasseril Apr 19 '18 at 10:24
  • I am not sure what the limit for the function call is, but the length field of a IPv4 UDP packet is only 16 bit, so there is no sense in using larger receive packet buffers. I've never used UDP on IPv6, but I think the maximum packet size will be large on IPv6. – Andreas H. Apr 19 '18 at 10:51
  • If you want a reliable, fast communication you either use TCP/IP or implement your own safe protocol over UDP/IP. The sender must wait for the client to acknowledge packets, the client must tell the server to resend missing / dropped packets and the client must sort the packets. – Andreas H. Apr 19 '18 at 10:54