[Libwebsockets] New user questions

Andy Green andy at warmcat.com
Tue Sep 6 02:45:25 CEST 2016



On September 6, 2016 4:44:34 AM GMT+08:00, tony at softins.co.uk wrote:
>Hi Andy, many thanks for your reply...
>
>Andy Green <andy at warmcat.com> wrote:
>> 
>> 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.
>
>Ah, the example I found at
>http://usualcarrot.com/libwebsockets-simple-websocket-server
>was doing what I described, but had not changed the callback name, nor
>the protocol

Lws has its own examples, eg

https://github.com/warmcat/libwebsockets/blob/master/plugins/protocol_dumb_increment.c

>string. Presumably the protocol strings, such as
>"dumb-increment-protocol" and
>"lws-command-protocol" are arbitrary, chosen by the implementor and
>only need
>to be agreed between the client and the server?

Yes that's a ws thing, not an lws thing.

>> >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.
>
>Ok, yes.
>
>> >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.
>
>Ok, that makes sense. So it is the incoming callback's responsibility
>to hand off
>the operation that would block to a different worker thread.
>
>> >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.
>
>Ok, so the worker thread I mentioned above could queue its answer as I
>do
>at present, request the callback, and then when the callback is invoked
>it could read the answer from the queue and write it to the websock.

Right.

>> >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.
>
>OK, that's good advice, thanks! Are you aware of any other websocket
>libraries, that might be implemented more on the single thread per
>socket
>architecture?

Nope, I wrote lws for my needs and it has been solving them.

>I found a Wikipedia page listing websocket implementations, and noticed
>that
>libwebsockets isn't listed. Maybe you could get it added! The page is
>at
>https://en.wikipedia.org/wiki/Comparison_of_WebSocket_implementations
>I'm going to take a look also at noPoll, which is listed there.

I'll look into the page, thanks.

-Andy

>Cheers
>Tony




More information about the Libwebsockets mailing list