<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><meta content="text/html;charset=UTF-8" http-equiv="Content-Type"></head><body ><div style='font-size:10pt;font-family:Verdana,Arial,Helvetica,sans-serif;'><div id="message"></div>By synchronous I mean if the program does not finish processing processing of first packet and packet 2,3 arrived does Erlang VM wait for handle_info to return? <div>Is it possible to lose sequnce of packets?<br><div>As far as I know handle_call is sync and handle_cast is async in gen_server.<br id="br3"><br id="br3"><br id="br3"><div id="signature"></div><div id="content"><br> ---- On Mon, 04 Jan 2021 17:50:48 +0330 <b> jesper.louis.andersen@gmail.com </b> wrote ----<br><br><blockquote style="border-left: 1px solid rgb(204, 204, 204); padding-left: 6px; margin-left: 5px;"><div><div dir="ltr"><div dir="ltr"><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;"><span style="font-family: Arial, Helvetica, sans-serif;">On Mon, Jan 4, 2021 at 2:40 PM George Hope <<a href="mailto:george@1w1g.com" target="_blank">george@1w1g.com</a>> wrote:</span><br></div></div><div class="x_-1478124645gmail_quote"><blockquote class="x_-1478124645gmail_quote" style="margin: 0.0px 0.0px 0.0px 0.8ex;border-left: 1.0px solid rgb(204,204,204);padding-left: 1.0ex;"><u></u><div><div style="font-family: Verdana, Arial, Helvetica, sans-serif;font-size: 10.0pt;"><div><span style="font-size: 10.0pt;">my questions are:</span><br></div><div><br></div><div> 1. is there a better way to do this? last time I made a mistake and read some messages more than once(I fixed that bug, but did not test my code in production yet, but it seems OK in tests). when packet size is unsigned integer Erlang can handle this for me but no success with ASCII encoded packet size.<br></div><div> 2. I tried to use {active, once} and  gen_tcp:recv but It did not work properly for me, Is this a safer approach?<br></div><div> 3. Is gen_server:handle_info synchronous? <br></div><div><br></div></div></div></blockquote><div><br></div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;">1. Rough idea:</div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;"><br></div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;">When you get a new bin in, you can probably just append it directly:</div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;"><br></div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;">handle_info({ConnType, _Sock, Data}, SoFar) -></div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;">    read_iso_packet(<<SoFar/binary, Data/binary>>, ...).</div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;"><br></div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;">This then makes the rest of the code simpler since it can just inspect that singular data block, trying to cut the head out of the binary in order to decode the ASCII value. Some solutions will return either {more, N, Bin} if more data is needed (N bytes) or {packet, Packet, Rest} if a packet was decoded. You then loop again on Rest after having handled the packet because you might have enough data for the next message already in the buffer. But this depends a bit on your socket mode being active or passive. It's often easier to just try decoding from the head. If you can get a full packet out, process and recur. If you don't have enough data, stuff it into the buffer and wait for more data to arrive. Unless you are looking at very high loads this is going to be efficient.</div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;"><br></div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;">2. {active, once} and {active, N} are very recommended! You call inet:setopts/2 on the socket once you have received a message:</div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;"><br></div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;">handle_info({ConnType, Socket, Data}, #state { socket = Socket, buffer = SoFar} = State) -></div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;">    ok = inet:setopts(Socket, [{active, once}]),</div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;">    read_iso_packet(<<SoFar/binary, Data/binary>>, State);</div></div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;"></div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;">It allows you to do other things in the process while you are waiting on the network socket for more data, increasing responsiveness of your system. Furthermore, it provides backpressure on the TCP socket if you end up in a situation where the sender outpaces your receiver. {active, once} is probably fast enough for most cases.</div><div><br></div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;">3. It's not clear what you mean by synchronous here. Other TCP data might arrive on the socket while you are executing handle_info/2 but as soon as you return it'll get called again with the new data. There's only a single process executing the handle_info/2 call, so you have some very neat linearity guarantees and you don't have to worry about a lot of problems that would normally be present in code using critical sections (mutexes, condition variables, ...).</div><div class="x_-1478124645gmail_default" style="font-family: arial, helvetica, sans-serif;"><br></div><br><div><br></div>-- <br><div dir="ltr" class="x_-1478124645gmail_signature">J.</div></div>
</div></blockquote></div></div></div></div><br></body></html>