Search code examples
socketsudpclient-server

Multiple UDP sockets and multiple clients


I have to write a program using UDP sockets and I'm having trouble understanding what should I do in a scenario I have.

I have a server and a client. The server receives datagrams on an INADDR_ANY socket and for each unique client that shows up, it will sendto() a lot of information to. Each client also sends data periodically to the server.

For each client that contacts the listening socket, lets call it 0, I create a separate socket for, so I can send data to it without clogging socket 0. What I want to do is move all communication with a specific client to the new socket. Can I do that? The goal is to make the communication easier, efficient and avoid clogging any sockets.

So questions I failed to find answers for are:

  • can I recv data from that socket from that specific client?
  • If not, won't having all the clients write to socket 0 clog it if I won't do recvfrom often enough?
  • If it's possible to recv data from a specific client on a separate socket, will that data come to BOTH socket 0 and the specific socket?

I know that TCP would work better for this but I have to use UDP. How should I do this? Is there an accepted "standard" of handling such situations?

Comment: I have a feeling I am misunderstanding UDP sockets but there's really very little tutorials on it when compared to TCP.


Solution

  • What I want to do is move all communication with a specific client to the new socket. Can I do that?

    You could create a new UDP socket, bind() it to a different port, and then instruct the client to start sending traffic to the new socket's port instead of the usual one; but note that there isn't really any advantage to be gained by doing that.

    If not, won't having all the clients write to socket 0 clog it if I won't do recvfrom often enough?

    Yes, but the usual solution that is to call recvfrom() often enough to keep up with the flow of incoming traffic, and/or to increase its SO_RECVBUF buffer size to make its incoming-data buffer big enough that it is inlikely to become full. One way to ensure recvfrom() is called often enough is to create a separate thread that does nothing but call recvfrom() in a loop and then hand off the data to another thread for more intensive processing. Run this network thread at higher priority if possible to make sure it doesn't get held off of the CPU by other threads.

    If it's possible to recv data from a specific client on a separate socket, will that data come to BOTH socket 0 and the specific socket?

    If you have two threads both calling recvfrom() on the same socket, then any given incoming UDP packet will be delivered to either one thread or the other, and it's impossible to predict which thread will receive which packet -- it will just be luck of the draw depending on what is the next packet in the socket's incoming buffer at the instant a particular thread calls recvfrom() on it. In general having multiple threads accessing a single socket is not a recommended design.

    I know that TCP would work better for this but I have to use UDP. How should I do this? Is there an accepted "standard" of handling such situations?

    I don't know about what is "standard", but I usually have a dedicated I/O thread that does nothing but read from (and if necessary, write to) the UDP socket. It sets the UDP socket to non-blocking mode, then loops around select() to recvfrom() any incoming UDP packets and append (in a thread-safe manner) both the incoming packet's data and its source-address/port info to a FIFO queue for other (less time-sensitive) threads to take out and work on later. That way even if a packet (or series or packets) takes a relatively long time to process, the result won't be that packets get dropped (although it might temporarily increase RAM usage as the FIFO grows larger)