[Libwebsockets] New user questions

Andy Green andy at warmcat.com
Mon Sep 5 20:41:32 CEST 2016



On September 5, 2016 10:12:20 PM GMT+08:00, tony at softins.co.uk wrote:
>Hi, I've just joined this list because I'm looking for somewhere to ask
>questions from the point of view of an experienced programmer who is
>completely new to libwebsockets. Please let me know if there is a more
>appropriate place.
>
>I've just started to look at libwebsockets as a way to add websocket
>handling to my multi-threaded application server as a replacement for
>the
>current architecture, which is AJAX long polling over HTTP to a simple
>http server embedded in the application.
>
>I have two main questions:
>
>1. I see that libwebsockets is structured as a single thread with an
>event loop and callbacks. So when I receive a message from the client,
>it causes a callback function to be called, such as
>callback_dumb_increment().
>
>In the examples I have seen, callback_dumb_increment() does a very
>simple
>string reversal and immediately returns the result as a message by

It... dumbly increments a number.

>calling
>libwebsocket_write().
>
>Am I correct in assuming that this callback executes within the main
>event
>loop thread?

Yes.  There are two basic styles of doing this stuff, 'throw a thread at it', and a nonblocking event loop in a single thread.  Both are valid and have advantages and disadvantages.

>What happens if the message handling needs to do something that will
>take
>some time, such as a database access, before it is able to send a
>response? Does this cause ALL message handling for all connections to
>be
>stalled until the callback returns?

No, you would schedule the work to happen in parallel and immediately return to the event loop.  When the work completes, it would ask for a callback when the connection is writeable.  When the work completed AND the outward connection can accept more data, then the connection gets a callback and you can write your data.

The event loop remains serialized in one thread, and never blocked, not for the work and not in the case the ongoing connection became full.

>I am used to having a separate execution thread for each open
>connection,
>so that when one of them is waiting for I/O, it doesn't block the
>others,
>and I'm having difficulty seeing how to achieve something similar with
>the
>single-threaded libwebsockets architecture.

The above method solves it.

>2. Other threads in my application generate events from time to time
>that
>need to be delivered to interested client connections. In the AJAX long
>polling architecture, these events are put into a per-client queue that
>then gets emptied and sent by a "poll" request from the client.
>
>It is one of the supposed advantages of a continuously-open websocket
>that
>such events could be sent to the client immediately over the socket
>without waiting for a poll. But what I have read about libwebsockets so
>far suggests to me that only the main thread is allowed to do
>libwebsocket_write() calls (although I may easily have misunderstood).
>So
>do I need some kind of message concentrator to funnel the event
>messages
>through?

The critical primitive is usually the state of the outgoing connection, not whatever you want to make happen.  You may have an event locally, but actually you cannot do anything useful with it if the outgoing connection cannot accept more data.  In the threaded method, this basic truth remains implicit because the write blocks your connection thread.  With lws single-threaded event loop method, you explicitly ask for a callback (on the main lws thread context... but you may ask for it from any thread) when you can write something; the callback comes at the time of your local event happening AND when the outgoing socket may be written to.

>The above questions no doubt betray my lack of knowledge about how
>properly to use libwebsockets, but if anyone could answer or point me
>to
>any resources or examples that deal with such real-life scenarios and
>not
>just "Hello world" examples, I would be very grateful indeed.

Your threading, locking and integration are all out of scope for lws.  It's all different depending on the platform, threading library and application.

The only lws api primitive you need to do it is to ask for a callback when writeable, and this can be found in every example.

But from the sound of it you are already completely invested in spawning threads every time a connection happens, and the blocking paradigm.  You might be happier looking for another websocket library that is based on the same scheme and also just throws threads and blocks.  Event loops and threading are used successfully together in eg, desktop evnironments, so it's not strange to mix the models, but a major advantage of event loops for this kind of work is elimination of per-connection thread and locking overhead.  You probably need to decide about if you want that or a threaded, blocking solution first.

-Andy

>Cheers
>Tony




More information about the Libwebsockets mailing list