[Libwebsockets] What is the proper way to send back websouckets response NOT to all connected clients

Andy Green andy at warmcat.com
Wed May 25 13:37:43 CEST 2016



On 05/25/2016 07:33 PM, Meir Yanovich wrote:
> Thanks for your thought provoking answer .
> so i understand that it better to response to client when he is ready to
> consomme the response data.  therefore i should use
> the lws_callback_on_writable(lws_get_context(wsi), wsi); function
> but where ?
> in the LWS_CALLBACK_RECEIVE   ?
> so the response in the LWS_CALLBACK_SERVER_WRITEABLE is wrong ?

Neither are wrong... they're just saying you'd like to feed the client 
more when it's ready.

Actually you can even express that wish from another (non lws-service) 
thread.

"When it's ready", when the baby has swallowed some of the previous 
food, and the kernel says it can take another spoonful, you will be 
notified by LWS_CALLBACK_SERVER_WRITEABLE.

At what point you asked to be notified is not really related.

-Andy

> On Wed, May 25, 2016 at 2:21 PM, Andy Green <andy at warmcat.com
> <mailto:andy at warmcat.com>> wrote:
>
>
>
>     On 05/25/2016 06:54 PM, Meir Yanovich wrote:
>
>         Hello all
>         i want to be able to send back response only to selected connected
>         clients and not as
>         shown in the example using :
>         lws_callback_on_writable_all_protocol.
>         i searched the mailing list and found this answer :
>         https://libwebsockets.org/pipermail/libwebsockets/2016-January/002177.html
>
>         As suggested i need to keep list of wsi amd user id's
>         I just didn't understand why i need to use
>         lws_callback_on_writable()
>
>
>     This is a "nonblocking vs blocking" network programming question
>     rather than a lws one.
>
>     Imagine you have three clients connected, that you want to send
>     stuff to.
>
>       - one is localhost.  He can eat the data as fast as you send it.
>
>       - the second is in another continent.  He is restricted how
>     quickly he can eat data.
>
>       - the third is on the London Underground with a 3G phone.  (As
>     opposed to the Taiwanese MRT, which has global coverage for phones
>     even underground, because it got started a bit later than 1906).
>
>     The only way to unify these guys is to modulate what is sent by when
>     they individually ACK what was sent before.  Otherwise who will hold
>     the increasing pile of data for the 3G phone when he is
>     incommunicado in a tunnel?
>
>         As you can see i will invoke function to response to selected users
>         In the LWS_CALLBACK_SERVER_WRITEABLE case
>
>         Now what i have in my web socket handler/callback function :
>         where do i need to use lws_callback_on_writable() ?
>
>
>     Fundamentally because different clients eat your data at different
>     rates, and sometimes their connectivity goes away for a while.
>
>     You cannot just spam data at each client because it became ready.
>     Threaded / blocking programming makes it look like that while
>     someone is eating the data quickly, but actually even there some
>     connections will block forever and you don't have infinite storage,
>     so you have the same problem.  One way or the other, you must hold
>     the data until the client can eat it, or you decide you don't want
>     to burn memory holding it any more and it will never get that data.
>
>     If you have to feed two babies, and one eats slower than the other,
>     the point is not that you have the food on the plate it's that the
>     individual baby is ready and willing for another spoonful; that will
>     decide the rate any progress is made and it's different for each baby.
>
>     That's why we talk about "when writable" as the primitive for the
>     individual connections rather than "when you have data to send".
>
>     -Andy
>
>         switch (reason) { case LWS_CALLBACK_ESTABLISHED:
>         pss->recive_all_from_client = 0; break; case
>         LWS_CALLBACK_SERVER_WRITEABLE: if (pss->recive_all_from_client
>         == 1) {
>         root = cJSON_CreateObject(); cJSON_AddItemToObject(root, "text",
>         cJSON_CreateString(pss->text_string));
>         cJSON_AddItemToObject(root, "id",
>         cJSON_CreateString(pss->id_string)); cJSON_AddItemToObject(root,
>         "msg",
>         cJSON_CreateString("Thanks!")); resp_json = cJSON_Print(root); n =
>         sprintf((char *)pout, "%s", resp_json); //m = lws_write(wsi, out,
>         sizeof(out), LWS_WRITE_TEXT); if (m < n) { lwsl_err("ERROR %d
>         writing to
>         di socket\n", sizeof(out)); return -1; } /* // Here i will keep
>         the wsi
>         and the user id in some vector or list */ //Invoke response to
>         selected
>         users ... } break; case LWS_CALLBACK_RECEIVE: if (len < 1) {
>         break; }
>         lwsl_notice("Request from server: %s \n", (const char *)in); cJSON *
>         user_root = cJSON_Parse((const char *)in); cJSON * user_type =
>         cJSON_GetObjectItem(user_root, "type"); cJSON * user_text =
>         cJSON_GetObjectItem(user_root, "text"); cJSON * user_id =
>         cJSON_GetObjectItem(user_root, "id"); cJSON * user_date =
>         cJSON_GetObjectItem(user_root, "date"); strcpy(pss->type_string,
>         user_type->valuestring); strcpy(pss->text_string,
>         user_text->valuestring); strcpy(pss->id_string,
>         user_id->valuestring);
>         strcpy(pss->date_string, user_date->valuestring);
>         pss->recive_all_from_client = 1; break; case
>         LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
>
>
>
>
>         _______________________________________________
>         Libwebsockets mailing list
>         Libwebsockets at ml.libwebsockets.org
>         <mailto:Libwebsockets at ml.libwebsockets.org>
>         http://libwebsockets.org/mailman/listinfo/libwebsockets
>
>



More information about the Libwebsockets mailing list