<div dir="ltr">Thanks Andy for your very informative answer , it sure made some things very clear on how lws + networking works .<br>so as im looking at the mirror example , i can see the server is actually collects the client transmit part (Tx) in to the session data structure . (per_session_data__lws_mirror) .<br>1. on LWS_CALLBACK_RECEIVE it fills the payload by the order they received in the FIFO container <br>2  on LWS_CALLBACK_SERVER_WRITEABLE it iterate through the collected massages and write back to the client .  from the FIFO container <br><br>Question :<br>.In my example i keep each session data ( each client which is connected ) with its own wsi pointer as a member in the session data structure .<br>in to hashmap so i could write back to them and update what other client did which works fine. <br>now if i will like to be able to response to the connected client and to other clients ( the one that i keep in the hashmap ) only from the uv_timer_start callback and not right away .<div>do you think it will be a problem ? </div><div>imagine that i will take the code from the mirror example which is in LWS_CALLBACK_SERVER_WRITEABLE and move it to the  </div><div>static bool response_to_client_cp(void* key, void* value, void* context) callback in my example . <br>and In addition it will iterate through the hashmap  to write back to other connections . ?<br><br><br>Thanks<br> <br><br><br><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Aug 1, 2016 at 1:37 AM, 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 August 1, 2016 1:24:49 AM GMT+08:00, Meir Yanovich <<a href="mailto:meiry242@gmail.com">meiry242@gmail.com</a>> wrote:<br>
>Hello<br>
>first of all i can't post full source code here. so i will try to<br>
>explain<br>
>the problem as best as i can<br>
<br>
</span>...<br>
<span class=""><br>
>I receiving WS calls on high rate , i capture them and process them .<br>
>now i have timer which invokes every 100ms , on this timer callback i<br>
>handle data caming from the session_data .<br>
>the problem is that the values i receive are wrong .is missing.<br>
<br>
</span>What does 'wrong' or 'missing' mean?  Either you received some rx data or not.<br>
<span class=""><br>
>probably  this is , i guess because the high rate of the WS calls i<br>
>receive<br>
>from the client .<br>
<br>
</span>Hm<br>
<span class=""><br>
>The question is , how do i handle the session_data to sync , isn't in<br>
>async<br>
>server they suppose to stack until they served ?<br>
<br>
</span>Not sure what you are really asking, but looking at your code, I think it will be 'no'.  Network programming over the actual internet doesn't look like that, in fact in terms of in -> process -> out the two sides' behaviours may be completely unrelated.  Rx may continuously pile in, no more tx may be possible for some period... then what?  What if the period is minutes?   Your server has infinite resources to buffer endless rx from many connections?<br>
<div><div class="h5"><br>
><br>
>#include "game_handler.h"<br>
>#include "simplog.h"<br>
><br>
><br>
>extern int debug_level;<br>
>connection_num_as_id = 0;<br>
>Hashmap *users_map_main = NULL;<br>
>//Array *gems_array = NULL;<br>
>uv_timer_t timeout_watcher;<br>
><br>
><br>
>//response to every 100ms   loop tick<br>
>static bool response_to_client_cp(void* key, void* value, void*<br>
>context)<br>
>{<br>
>struct per_session_data__apigataway *pss =<br>
>(struct per_session_data__apigataway *)hashmapGet(users_map_main, (char<br>
>*)key);<br>
>        // HERE the values are not as expected<br>
>int s = pss->status;<br>
><br>
>return true;<br>
>}<br>
><br>
>static void game_loop_cb(uv_timer_t* handle) {<br>
><br>
>ASSERT(handle != NULL);<br>
>ASSERT(1 == uv_is_active((uv_handle_t*)handle));<br>
><br>
><br>
>if (hashmapSize(users_map_main)>0)<br>
>{<br>
>hashmapForEach(users_map_main, &response_to_client_cp, users_map_main);<br>
>}<br>
><br>
><br>
>}<br>
><br>
>int callback_wsapi(struct lws *wsi, enum lws_callback_reasons reason,<br>
>void *user, void *in, size_t len)<br>
>{<br>
>if (users_map_main == NULL)<br>
>{<br>
>users_map_main = hashmapCreate(10, str_hash_fn, str_eq);<br>
>}<br>
>//char *resp_json;<br>
>unsigned char response_to_client[LWS_PRE + 1024];<br>
>struct per_session_data__apigataway *pss =<br>
>(struct per_session_data__apigataway *)user;<br>
>unsigned char *p_response_to_clientout = &response_to_client[LWS_PRE];<br>
>int n;<br>
>  switch (reason) {<br>
>case LWS_CALLBACK_PROTOCOL_INIT:<br>
>{<br>
><br>
>uv_timer_init(lws_uv_getloop(lws_get_context(wsi),<br>
>0),&timeout_watcher);<br>
>//every 100ms<br>
>uv_timer_start(&timeout_watcher, game_loop_cb, 1000, 100);<br>
>break;<br>
>}<br>
>case LWS_CALLBACK_ESTABLISHED:<br>
>{<br>
><br>
><br>
>break;<br>
>}<br>
>case LWS_CALLBACK_SERVER_WRITEABLE:<br>
>{<br>
><br>
>       struct per_session_data__apigataway *pss  =<br>
>hashmapPut(users_map_main, pss->player_id, pss);<br>
><br>
><br>
>break;<br>
>}<br>
>default:<br>
>lwsl_notice("Invalid status \n");<br>
><br>
>}<br>
>break;<br>
>}<br>
>case LWS_CALLBACK_RECEIVE:<br>
>{<br>
>if (len < 1)<br>
>{<br>
>break;<br>
>}<br>
>pss->binary = lws_frame_is_binary(wsi);<br>
><br>
>memcpy(&pss->request_from_client_buf, in, len);<br>
>>request_from_client_buf);<br>
>pss->recive_all_from_client = 1;<br>
>//Only invoke callback back to client when baby client is ready to eat<br>
>lws_callback_on_writable(wsi);<br>
<br>
</div></div>What will happen if you receive multiple rx inbetween the connection becoming writeable?<br>
<br>
If the client just spams ws frames how it likes, there is nothing to guarantee when they arrive or how often the tcp connection going back to the client has some more space.<br>
<br>
Tcp guarantees stuff will be presented as arriving in the right order if possible.  But to live up to that guarantee, there are various restrictions about exponential retry backoff and disordered fragment buffering that can create unpredictable latencies followed by "several packets arriving at once" as the already-received disordered packets are replayed.  Tcp allows fragments to be coalesced anywhere along the way.  So the rx size you get at the callback has no guarantee to be related to the packet size that was sent.  That is one reason why lws itself uses bytewise state machines everywhere.<br>
<br>
There is nothing globally regulating that the server sees the client becoming writeable in lockstep with the remote client sending one packet.  Network programming is something else.<br>
<br>
Look at how the mirror example deals with it<br>
<br>
 - a fifo for rx data, to deal with multiple rx<br>
<br>
 - if the situation starts to get beyond our fifo, use of rx flow control to signal to the remote peer using the tcp window that we are not keeping up with what he's sending (from his perspective, the socket connected to us becomes unwritable once we get to filling our rx fifo and becomes writable again if and when we caught up)<br>
<br>
-Andy<br>
<span class=""><br>
>break;<br>
>}<br>
><br>
>case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:<br>
><br>
>break;<br>
><br>
>case LWS_CALLBACK_WS_PEER_INITIATED_CLOSE:<br>
>{<br>
>break;<br>
><br>
>}<br>
><br>
>default:<br>
>break;<br>
>}<br>
><br>
>return 0;<br>
>}<br>
><br>
><br>
</span>>------------------------------------------------------------------------<br>
><br>
>_______________________________________________<br>
>Libwebsockets mailing list<br>
><a href="mailto:Libwebsockets@ml.libwebsockets.org">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></div><br></div>