libwebsockets: Simple HTTP server

I was quite surprised that there aren’t many WebSocket libraries for C. I made a small research and found this nice list of various implementations on wikipedia. It says that there are only 2 implementations of Web Sockets in pure C (not C++) so I made a quick look at both of them and they look pretty complicated but because I didn’t have any other option I stayed with libwebsockets which seems to be up to day (according to the git log) and it can be easily used as a web server as well. The only caveat here is that there is no “Hello world” tutorial for complete dummies (well, that’s what I’m trying to put right).

I don’t have any particular reason to use C because I could do the same way more easily with node.js I was just curious how complicated it is to make web socket or web server based on some library and compare performance to node.js, nginx or Apache. Later maybe add support for threads, scaling and whatever I want to play with.

Writing a web server

This tutorial is going to be only about writing a simple single-threaded web server. Maybe like a little extended “Hello world” demo from node.js website.
In order to compile this tutorial you have to download libwebsockets and compile them. You don’t have to use any IDE for this tutorial since it’s going to be just a single C file.

When I saw this only example using libwebsocket I felt like this.
Well, it turned out that it’s really not that complicated and if you spend a while playing with it, it all makes sense.

Ok, so let’s first include some header files.

The most important function is our callback that is called by the libwebsocket service every time a request occurs (well, in this case a better word could be probably “event”).

LWS_CALLBACK_HTTP is the only callback we'll care about. Definition in libwebsockets.h is pretty clear about it. Default response for / will be Hello, World! and for any other request it tries to find corresponding file on disk relatively from the current working directory.
libwebsockets_serve_http_file() writes automatically response headers like Content-length and HTTP version and then takes resource's absolute path and dumps its content as response. It can't detect resource's MIME type so you have to specify it manually. For more information on how this function works and how you can send your own headers see its source code.

If I wanted to make this tutorial very simple I could leave the switch statement just like:

This callback would reply to every request with Hello, World! but this would be too easy :).

The second thing we have to do is to define a structure that tells libwebsocket what protocols are we going to implement.

Just note that the { NULL, NULL, 0} is mandatory because deep inside libwebsockets, it needs to know where the protocols array ends.

The last thing is creating the libwebsockets context and main loop:

I think this is self-explanatory. You can try to set different delays than 50 ms and see what happens when you run some stress benchmark like ab.

In order to compile this example you can read this short article.
If you were successful, you can run it and see what it prints into your console. In my case it was this:

Then open http://localhost:8080 in your browser and you should see just Hello, World! like on this screenshot.

As you can see in your console, libwebsockets service calls more callbacks than we handle. But this is right, we are interested in just one event and don’t need to care about the rest.

At the end I tried all combinations that can occur. That’s an image, a HTML page and a text file. Here you can see that it was processed by the browser as expected.

There’s maybe one caveat. This web-server tries to find all resources relatively from the current working directory which is not very safe (you can use /../../.. and get into any directory you want) but also it’s not very practical when debugging.

For instance Xcode generates very long paths such as /Users/martin/Library/Developer/Xcode/DerivedData/libwebsockets-webserver-catfyrvtlzsybdakzdgpqzeiroyc/Build/Products/Debug/hello.txt and it's a bit annoying to copy my test resources into that directory by hand

By the way, full source code in one file is on


I think libwebsockets is a very nice library that helps you a lot even when you could do the same functionality like this web-server by your-self. I doesn’t store any per-user data (that’s what the void *user pointer can be user for) and doesn't support multithreading out of the box.