1
votes

I am wring a small http server which is using the Microsoft Windows WinSock API.

Do I need to apply multithreaded logic when handling multiple users?

Currently Windows sends a message when there is a network event and each message carried (in wParam) the socket to be used in either send() or recv().

When client A connects and requests a couple of files usually a number of socket are created by Winsock. My server then get a message that "send this file to socket 123" and later "send that file to socket 456"

When another client connect it too gets a few sockets, say 789 and 654.

My server then respond to requests to send data using supplied socket number. It does not have to know who wants the file since the correct file has to be sent to the right socket.

I do not know whether Windows itself uses multiple threads when handling accepting connection and sending the message down to my program.

So my question is:

Do I need to apply multithreaded logic when handling multiple users? And if so at what point should I create a thread?

2

2 Answers

2
votes

You typically use a thread per socket. And if you are accepting connections, a thread in a loop to block, waiting for an incoming connection socket. You then create a new thread and pass this socket handle to the new thread to handle. When that connection is closed and done with, simply let that thread terminate (or join). This is the basis of a threaded server.

in psudo code...

loop {
  socket = accept();
  new ThreadHandler( socket )
}

Using a single thread to handle multiple sockets is tricky, mainly because the thread can block (stop, waiting) while its writing, or more often, reading from a socket. It's not for the faint hearted.

0
votes

For most applications, there is no point in using multiple threads to handle network connections. I've made a small writeup in an answer to this question.

Multiple threads become useful when handling the received data requires an unpredictable amount of CPU time, for example in database servers, or when the program structure does not allow for requests to be handled asynchronously.

There is also a third option, the "worker pool". A single thread handles all incoming connections and deserializes incoming requests, and then passes off work items to a pool of threads that handle one item at a time.

This way, simply opening a connection does not yet consume the resources needed for an entire thread, and system load is implicitly limited by the number of threads in the pool.