<!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-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt;"><div>I have Erlang SSL TCP socket which has a permanent TCP connection to other party,<br></div><div>we use a protocol similar to ISO8583 protocol four first byte is a packet size which is ASCII encoded.<br></div><div>Based on Erlang inet documentation (<a target="_blank" href="https://erlang.org/doc/man/inet.html">https://erlang.org/doc/man/inet.html</a>) It only supports unsigned integer for packet size.<br></div><div> <br></div><div>``` The header length can be one, two, or four bytes, and containing an unsigned integer in big-endian byte order.```<br></div><div><br></div><div>right now I use gen_server handle_info, as soon as I receive a packet I read first four byte then compare it to Binary size and if the binary size is small I do nothing and put recieved binary to LastBin and wait for rest of packet and If more than one msg is in packet I call read_iso packet several times, short sample if what I do is like this:<br></div><div>```<br></div><div>handle_info({ConnType, _Socket, Bin}, {BSSl, BProtocol, Psize, OSocket, LastBin})<br></div><div> when ConnType =:= ssl; ConnType =:= tcp -><br></div><div> logger:debug("mp_back:Got response from backend~w", [Bin]),<br></div><div> read_iso_packet(Bin, {BSSl, BProtocol, Psize, OSocket, LastBin})<br></div><div> end.<br></div><div>read_iso_packet(Bin, {BSSl, BProtocol, Psize, Socket, LastBin})<br></div><div> when size(<<LastBin/binary, Bin/binary>>) < 5 -><br></div><div> {noreply, {BSSl, BProtocol, Psize, Socket, <<LastBin/binary, Bin/binary>>}};<br></div><div>read_iso_packet(Bin, {BSSl, BProtocol, Psize, Socket, LastBin})<br></div><div> when size(<<LastBin/binary, Bin/binary>>) > 4 -><br></div><div> Packe_Size = get_packet_size(binary:part(<<LastBin/binary, Bin/binary>>, 0, 4)),<br></div><div> logger:debug("mp_back:packet_size==~w", [Packe_Size]),<br></div><div> logger:debug("mp_back:bin_size==~w", [size(Bin)]),<br></div><div> read_iso_packet(Packe_Size + 4 - size(<<Bin/binary, LastBin/binary>>),<br></div><div> Packe_Size,<br></div><div> <<LastBin/binary, Bin/binary>>,<br></div><div> {BSSl, BProtocol, Psize, Socket, LastBin}).<br></div><div><br></div><div>read_iso_packet(0, _Packe_Size, Bin, {BSSl, BProtocol, Psize, Socket, _LastBin}) -><br></div><div> do_somthing(server_response, CSocket, Bin),<br></div><div> {noreply, {BSSl, BProtocol, Psize, Socket, <<>>}};<br></div><div>read_iso_packet(SS, Packe_Size, Bin, {BSSl, BProtocol, Psize, Socket, _LastBin})<br></div><div> when SS < 0 -><br></div><div> do_somthing(server_response, CSocket, [binary:part(Bin, 0, Packe_Size + 4)]), <br></div><div> read_iso_packet(binary:part(Bin, Packe_Size + 4, byte_size(Bin) - (Packe_Size + 4)),<br></div><div> {BSSl, BProtocol, Psize, Socket, <<>>});<br></div><div>read_iso_packet(SS, _Packe_Size, Bin, {BSSl, BProtocol, Psize, Socket, _LastBin})<br></div><div> when SS > 0 -><br></div><div> logger:debug("mp_back: Small data going to read next~w", [Bin]),<br></div><div> {noreply, {BSSl, BProtocol, Psize, Socket, Bin}}.<br></div><div><br></div><div>get_packet_size(Bin) -><br></div><div> {ok, [A], _} = io_lib:fread("~16u", binary_to_list(binary:part(Bin, 0, 1))),<br></div><div> {ok, [B], _} = io_lib:fread("~16u", binary_to_list(binary:part(Bin, 1, 1))),<br></div><div> {ok, [C], _} = io_lib:fread("~16u", binary_to_list(binary:part(Bin, 2, 1))),<br></div><div> {ok, [D], _} = io_lib:fread("~16u", binary_to_list(binary:part(Bin, 3, 1))),<br></div><div> A * 1000 + B * 100 + C * 10 + D.<br></div><div>```<br></div><div>my questions are:<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><br></body></html>