[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:21:09 CEST 2016



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
> http://libwebsockets.org/mailman/listinfo/libwebsockets
>



More information about the Libwebsockets mailing list