<div dir="ltr"><span style="font-size:12.8px">Thanks for your thought provoking answer .</span><div style="font-size:12.8px">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 <br>but where ? </div><div style="font-size:12.8px">in the LWS_CALLBACK_RECEIVE   ? <br>so the response in the LWS_CALLBACK_SERVER_WRITEABLE is wrong ? </div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, May 25, 2016 at 2:21 PM, Andy Green <span dir="ltr"><<a href="mailto:andy@warmcat.com" target="_blank">andy@warmcat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><br>
<br>
On 05/25/2016 06:54 PM, Meir Yanovich wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hello all<br>
i want to be able to send back response only to selected connected<br>
clients and not as<br>
shown in the example using :<br>
lws_callback_on_writable_all_protocol.<br>
i searched the mailing list and found this answer :<br>
<a href="https://libwebsockets.org/pipermail/libwebsockets/2016-January/002177.html" rel="noreferrer" target="_blank">https://libwebsockets.org/pipermail/libwebsockets/2016-January/002177.html</a><br>
<br>
As suggested i need to keep list of wsi amd user id's<br>
I just didn't understand why i need to use lws_callback_on_writable()<br>
</blockquote>
<br></span>
This is a "nonblocking vs blocking" network programming question rather than a lws one.<br>
<br>
Imagine you have three clients connected, that you want to send stuff to.<br>
<br>
 - one is localhost.  He can eat the data as fast as you send it.<br>
<br>
 - the second is in another continent.  He is restricted how quickly he can eat data.<br>
<br>
 - 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).<br>
<br>
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?<span class=""><br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
As you can see i will invoke function to response to selected users<br>
In the LWS_CALLBACK_SERVER_WRITEABLE case<br>
<br>
Now what i have in my web socket handler/callback function :<br>
where do i need to use lws_callback_on_writable() ?<br>
</blockquote>
<br></span>
Fundamentally because different clients eat your data at different rates, and sometimes their connectivity goes away for a while.<br>
<br>
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.<br>
<br>
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.<br>
<br>
That's why we talk about "when writable" as the primitive for the individual connections rather than "when you have data to send".<br>
<br>
-Andy<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
switch (reason) { case LWS_CALLBACK_ESTABLISHED:<br>
pss->recive_all_from_client = 0; break; case<br>
LWS_CALLBACK_SERVER_WRITEABLE: if (pss->recive_all_from_client == 1) {<br>
root = cJSON_CreateObject(); cJSON_AddItemToObject(root, "text",<br>
cJSON_CreateString(pss->text_string)); cJSON_AddItemToObject(root, "id",<br>
cJSON_CreateString(pss->id_string)); cJSON_AddItemToObject(root, "msg",<br>
cJSON_CreateString("Thanks!")); resp_json = cJSON_Print(root); n =<br>
sprintf((char *)pout, "%s", resp_json); //m = lws_write(wsi, out,<br>
sizeof(out), LWS_WRITE_TEXT); if (m < n) { lwsl_err("ERROR %d writing to<br>
di socket\n", sizeof(out)); return -1; } /* // Here i will keep the wsi<br>
and the user id in some vector or list */ //Invoke response to selected<br>
users ... } break; case LWS_CALLBACK_RECEIVE: if (len < 1) { break; }<br>
lwsl_notice("Request from server: %s \n", (const char *)in); cJSON *<br>
user_root = cJSON_Parse((const char *)in); cJSON * user_type =<br>
cJSON_GetObjectItem(user_root, "type"); cJSON * user_text =<br>
cJSON_GetObjectItem(user_root, "text"); cJSON * user_id =<br>
cJSON_GetObjectItem(user_root, "id"); cJSON * user_date =<br>
cJSON_GetObjectItem(user_root, "date"); strcpy(pss->type_string,<br>
user_type->valuestring); strcpy(pss->text_string,<br>
user_text->valuestring); strcpy(pss->id_string, user_id->valuestring);<br>
strcpy(pss->date_string, user_date->valuestring);<br>
pss->recive_all_from_client = 1; break; case<br>
LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:<br>
<br>
<br>
<br>
<br></span>
_______________________________________________<br>
Libwebsockets mailing list<br>
<a href="mailto:Libwebsockets@ml.libwebsockets.org" target="_blank">Libwebsockets@ml.libwebsockets.org</a><br>
<a href="http://libwebsockets.org/mailman/listinfo/libwebsockets" rel="noreferrer" target="_blank">http://libwebsockets.org/mailman/listinfo/libwebsockets</a><br>
<br>
</blockquote>
</blockquote></div><br></div>