6
votes

I am writing a C++ application on Linux. My application has a UDP server which sends data to clients on some events. The UDP server also receives some feedback/acknowledgement back from the clients.

To implement this application I used a single UDP Socket(e.g. int fdSocket) to send and receive data from all the clients. I bound this socked to port 8080 and have set the socket into NON_BLOCKING mode.

I created two threads. In one thread I wait for some event to happen, if an event occurs then I use the fdsocket to send data to all the clients(in a for loop).

In the another thread I use the fdSocket to receive data from clients (recvfrom()). This thread is scheduled to run every 4 seconds (i.e. every 4 seconds it will call recvfrom() to retrieve the data from the socket buffer. Since it is in NON-BLOCKING mode the recvfrom() function will return immediately if no UDP data is available, then I will go to sleep for 4 secs).

The UDP Feedback/Acknowledge from all the clients has a fixed payload whose size is 20bytes.

Now I have two questions related to this implementation:

  1. Is it correct to use the same socket for sending/receiving UDP data with Mulitiple clients ?
  2. How to find the maximum number of UDP Feedback/Acknowledge Packets my application can handling without UDP Socket Buffer Overflow (since I am reading at every 4secs, if I receive lot of packets within this 4 seconds I might loose some packet ie., I need to find the rate in packets/sec I can handle safely)?

I tried to get the Linux Socket Buffer size for my socket (fdsocket) using the function call getsockopt(fdsocket,SOL_SOCKET,SO_RCVBUF,(void *)&n, &m);. From this function I discover that my Socket Buffer size is 110592. But I am not clear as what data will be stored in this socket buffer: will it store only the UDP Payload or Entire UDP Packet or event the Entire Ethernet Packet? I referred this link to get some idea but got confused.

Currently my code it little bit dirty , I will clean and post it soon here.

The following are the links I have referred before posting this question.

  1. Linux Networking
  2. UDP SentTo and Recvfrom Max Buffer Size
  3. UDP Socket Buffer Overflow Detection
  4. UDP broadcast and unicast through the same socket?
  5. Sending from the same UDP socket in multiple threads
  6. How to flush Input Buffer of an UDP Socket in C?
  7. How to find the socket buffer size of linux
  8. How do I get amount of queued data for UDP socket?
3
Why only every 4 seconds? Why not just have that thread sit in a select() call waiting for data?Collin
@Collin Since UDP is not reliable we have implemented the following mechanism. For every UDP packet sent to a client I expect a acknowledgement packet (a simple UDP packet with a fixed string.) back from the client. If I didn't get the acknowledgement packet from a client then I will again resend the packet after 4 secondsDinesh P.R.
Ok, but with that setup the server is going to think packets are lost even when they're not. What happens when a packet is sent just after the client has read the socket? With network timings, the server will think there was never a response even though there was. There's still no reason not to respond right away. Instead of rolling your own reliability though you might look at using TCP or something like: udt.sourceforge.netCollin
You should either use select() or use blocking mode and set a 4-second SO_TIMEOUT. That way if a packet arrives within the 4 seconds you will read it immediately, instead of wasting time in the sleep.user207421
@EJP . Your comment is great, it gives clear idea to me, I will try to implement that way. I want to vote your comment up, but unfortunately I have clicked it twice, the system is not allowing me to vote your comment :-(Dinesh P.R.

3 Answers

6
votes

Having socket reading at fixed interval of four seconds definitely sets you up for losing packets. The conventional tried-and-true approach to non-blocking I/O is the de-multiplexer system calls select(2)/poll(2)/epoll(7). See if you can use these to capture/react to your other events.

On the other hand, since you are already using threads, you can just do blocking recv(2) without that four second sleep.

Read Stevens for explanation of SO_RCVBUF.

3
votes

Q: Is it correct to use the same socket for sending/receiving UDP data with Mulitiple clients ?

A: Yes, it is correct.

Q: How to find the maximum number of UDP Feedback/Acknowledge Packets my application can handling without UDP Socket Buffer Overflow (since I am reading at every 4secs, if I receive lot of packets within this 4secs I might loose some packet ie., I need to find the rate : noofpackets/sec I can handle safely)?

A: The bottleneck might be the network bandwidth, or CPU, or memory. You could simply do a testing, using a client which sends ACK to the server with consecutive number, and verify whether there is packet loss at the server.

3
votes

You can see the maximum allowed buffer size:

sysctl net.core.rmem_max

You can set the maximum buffer size you can use by:

sysctl -w net.core.rmem_max=8388608

You can also set the buffer size at run-time (not exceeding the max above) by using setsockopt and changing SO_RCVBUF. You can see the buffer level by looking at /proc/net/udp.

The buffer is used to store the UDP header and application data, rest belong to lower levels.