C HTTP server - multithreaded model?

I am currently writing an HTTP server in C to learn about C, network programming, and HTTP. I have implemented most of the simple things, but I only process one connection at a time. I am currently thinking about how to effectively add multitasking to my project. Here are some of the options I was thinking about:

  • Use one thread for each connection. Simple but cannot handle many connections.
  • Use non-blocking API calls and handle everything in one thread. It sounds interesting, but using select() and is said to be too slow.
  • Some other multi-threaded model, for example. something complicated like lighttpd . (Maybe) the best solution, but (maybe) too hard to implement.

Any thoughts on this?

+4
source share
5 answers

There is no single best model for writing multi-tasking network servers. Different platforms have different solutions for high performance (I / O completion ports, epoll, kqueues). Be careful with maximum mobility: some functions are imitated on other platforms (i.e. select() available on Windows) and give very low performance because they simply map to some other proprietary model.

In addition, there are other models on your list. In particular, the classic UNIX "pre-fork" model.

In all cases, use any form of asynchronous I / O when available. If this is not the case, pay attention to non-blocking synchronous I / O. Build your HTTP library around asynchronous streaming, but keep the I / O bit. It is much more complicated than it seems. This usually involves recording machine states for your protocol interpreter.

This last bit is the most important because it will allow you to experiment with different views. It may even allow you to write a compact kernel for each platform of local high-performance tools and change this kernel from one platform to another.

+4
source

Yes, make one that interests you. When you are done with this, if you are not at all afraid of a project, compare it, profile and try one of the other methods. Or, even more interesting, to give up work, take lessons and move on to something completely different.

+4
source

You can use the event loop, as in node.js:

Source code node (c, C ++, javascript)

https://github.com/joyent/node

Ryan Dahl (the creator of node) argues for the design of node.js, a non-blocking io, and an event loop as an alternative to multithreading on a web server.

http://www.yuiblog.com/blog/2010/05/20/video-dahl/

Douglas Crockford discusses the cycle of events in Scene 6: Loopage (Friday, August 27, 2010)

http://www.yuiblog.com/blog/2010/08/30/yui-theater-douglas-crockford-crockford-on-javascript-scene-6-loopage-52-min/

The Douglas Crockford Index is above the conversation (if additional background information is required). This does not really apply to your question.

http://yuiblog.com/crockford/

+2
source

Look at the most efficient socket polling model on the platform - epoll (linux), kqueue (freebsd), WSAEventSelect (Windows). Perhaps combined with the thread pool, handle N connections per thread. You can always start with select , and then replace the more efficient model when it works.

0
source

A simple solution can have several processes: one process accepts connections and as soon as the connection is established fork and processes the connection in this child process.

An interesting version of this technique is used by the SER / OpenSER / Kamailio SIP proxy: there is one main process that accepts connections and several child workflows connected through channels. The parent sends the new filedescriptor through the socket. See this excerpt from the book in 17.4.2. Transfer file descriptors through UNIX domain sockets. OpenSER / Kamailio SIP proxies are used for high-performance SIP processing, where performance is a huge problem and they do very well with this method (plus shared memory for exchanging information). However, multithreading is easier to implement.

0
source

All Articles