[Libwebsockets] What is the proper way to send back websouckets response NOT to all connected clients
Meir Yanovich
meiry242 at gmail.com
Wed May 25 13:48:02 CEST 2016
Thanks Andy you well explained the subject.
On Wed, May 25, 2016 at 2:37 PM, Andy Green <andy at warmcat.com> wrote:
>
>
> 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
>>
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://libwebsockets.org/pipermail/libwebsockets/attachments/20160525/58043b99/attachment-0001.html>
More information about the Libwebsockets
mailing list