chinmaymhatre91
chinmaymhatre91

Reputation: 35

Use of multiple sockets in Multithreaded UDP server

Requirement: 

I need to write a server that should be able to receive multiple client connections(FCFS order) and be able to process each client in a separate thread, so that the processing looks like as if all the clients are served concurrently. The transport protocol being employed should be UDP. Also several round trips of data transfer would happen between client and server, and the data that is received from the client has to be stored at the server side for further processing with respect to this client.

Implementation:

To achieve this, I employed a queue/threadpool mechanism. Initially I create a pool of fixed number of threads and have a queue datastructure to store client-addresses. This queue is shared among all threads, and hence I used "mutex" to lock/unlock this queue. In the main server thread, I create a socket, bind it to a global port/address and then I block the server on "recvfrom" call. Any client that wants to communicate with the server sends a "Hi" message to the main thread server listening on the global port-address. The main server thread upon receiving this "Hi" datagram pushes the client's sockaddr structure onto the queue and goes back to block on the "recvfrom" call to accept other clients.

Any of the pool threads that gets a lock on the queue, pops the client's address and starts processing this client all by itself. That is, the pool thread will now create a socket, bind it to a different port than the global port and sends this port-address to the client using the client's address it has popped off. At the client side, after sending the "Hi" message, it blocks on "recvfrom" call and once it receives a message from the server(with a different port), it stores this port/address and from then on, it communicates with the server only using this new port sent by the pool server thread.

Clarification needed:

I have noticed in many Stack overflow questions that A SINGLE SOCKET is always sufficient in multithreaded UDP server, but according to my requirements I think I need multiple UDP sockets, each one catering to a client. Please provide me suggestions on my approach of threaded UDP server for my requirements

EDIT: Improved the design

Thanks for all your comments and discussions about my design. After grasping all your views on single-socket connection and context switching, I have an improved design in mind. Please provide feedback on my improved design

In this implementation, I am going to use only one global UDP socket that is bound to a globally known port-address. Just like before, I will create a fixed number of threads initially, say 5 threads. Then I perform recvfrom() on the single socket in all my threads. Whichever thread receives the datagram first, will be able to know three things out of this datagram:

Based on the information above, the server thread will process the data based on the process number and sent reply to the same client from which it received. After processing data and sending the reply(if necessary), this thread will go back to blocking on the recvfrom() call.

Also, details about various clients would be stored in global hash table and maps(accessible to all threads), so that any thread could access it to process according to that particular client.

Changes at the client side: The server should be able to know what processing it has to do on the client data. Hence the client would send process number along with the data.

Upvotes: 2

Views: 6734

Answers (2)

SergeyA
SergeyA

Reputation: 62613

Well, I am not sure where those requirements are coming from - mostly, are those for real life program or for some sort of assignment/interview/etc.

I will continue on presumption this is a real-life program, since I am not helping anybody with assignments :)

UDP is not connection-oriented protocol (even though UDP sockets can be 'connected', but this just adds confusion). It is a message-oriented protocol. Now, the first question in designing thread model is always 'do I need thread model here?' You will need thread if you have operations which can be performed independently of each other and take noticeable time. In your case, it depends on what you really do with the message. Let's assume, you have some processing on it and this process time is significant as compared to number of potential simultaneous cliens (remember, there are successfull single-thread Web servers! There is nothing wrong in simply doing all your requests single-threaded).

Design-wise, I do not think the idea of giving new port to the client to connect is a good idea. There are several reasons for this, and one of those might be a firewall between your client and server. Implementation-wise it is also not straightforward, and somehow imitates TCP with UDP. If you need TCP, use TCP, do not try to build TCP over UDP - you will not succeed.

What I suggest instead is have a single listener on the socket, which would dispatch requests (together with sender information) to worker threads, which will send the reply back to the client. Remember, for UDP you do not need to send response over the same socket you used to process request.

Upvotes: 1

rkachach
rkachach

Reputation: 17375

Once socket is enough because you are able to identify the client each time you receive a packet by calling recvfrom by using its source address (src_addr):

recvfrom(int sockfd, void *buf, size_t len, int flags,
             struct sockaddr *src_addr, socklen_t *addrlen);

Now, this solution has a single reception point. That means the server has to receive the data and then pass it to the thread that should perform the process. This reduce the parallelism of the single socket solution since you are using one port only.

In my opinion your solution is better in terms of parallelism since your threads are running on different ports, so they can serve several clients in parallel specially if your machine has several processors and several network cards that could be used to attend your clients. In the best case you may have several threads running in parallel, in different processors each one serving a client coming from different network interface.

EDIT:

After discussing your design with David, he convinced me that having several sockets would lead to several context switches which may slow down the server performance. So the best in this case is to use several threads but a single socket for all the clients.

Upvotes: 3

Related Questions