[erlang-questions] SOLVED Re: how to use sockets in erlang

Ivan Uemlianin ivan@REDACTED
Fri Jun 17 13:39:39 CEST 2011


Dear Jesper

Thank you very much for your help!

>>     Result = gen_tcp:recv(Socket, 4096, 5000),
>
> The Erlang semantics here are different. You are blocking until you
> have exactly 4096 bytes of data. If less is received, you will get
> {error, closed} back, or a timeout after 5000 ms. You should be
> calling gen_tcp:recv(Socket, 0, 5000) ...

Yes! This works:

     {ok, Result} = gen_tcp:recv(Socket, 0, 5000),

Thank you for your other comments too.  I'll shape up the rest of the code.

Best wishes

Ivan


On 17/06/2011 12:32, Jesper Louis Andersen wrote:
> On Fri, Jun 17, 2011 at 13:10, Ivan Uemlianin<ivan@REDACTED>  wrote:
>
> I am just shooting in the dark here, but I have a guess at what is wrong:
>
>> Python version --- works:
>>
>>     jsondata = json.dumps(data) + "\n"
>>     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>     s.connect((appliance_host, appliance_port))
>>     s.send(jsondata)
>>     returndata = s.recv(4096)
>
> The Python recv semantics follow that of the unix kernels recv(2)
> call. I.e., the 4096 is a buffer and you will get at most 4096 bytes,
> or less than that.
>
>> Erlang version --- doesn't work:
>>
>>     JsonData = list_to_binary(mochijson2:encode(Data) ++<<10>>),
>
> You usually don't have to call list_to_binary/1 here. The value
> [mochijson2:encode(Data),<<10>>] is an iolist() and sockets take
> iolist() types. That way, you won't be creating new binaries but just
> refer to already existing binaries in lists. It is much faster than
> building the binary first and then shoving it out the socket. It is a
> common idiom to make Erlang go fast when rendering data structures to
> output. Look up iolist()s. They are a key element to make your code go
> fast as it avoids a large number of binary constructions.
>
>>     {ok, Socket} = gen_tcp:connect(?APPLIANCE_HOST, ?APPLIANCE_PORT,
>>                                   [inet,
>>                                    binary,
>>                                    {active, false},
>>                                    {packet, 0}]),
>>     ok = gen_tcp:send(Socket, JsonData),
>>     Result = gen_tcp:recv(Socket, 4096, 5000),
>
> The Erlang semantics here are different. You are blocking until you
> have exactly 4096 bytes of data. If less is received, you will get
> {error, closed} back, or a timeout after 5000 ms. You should be
> calling gen_tcp:recv(Socket, 0, 5000) and then use byte_size(X) on the
> result yourself. It also means you will have to drain the socket
> yourself in a separate function. The solution is to figure out what
> the stream-semantics and syntax is and handle that with a couple of
> Erlang functions.
>
> Another important thing to look out for is that in Erlang the Socket
> is a port() bound to the connecting process (by default -- the
> controlling process can change with the controlling_process call). If
> the bound process dies, the socket closes. As soon as you begin
> passing sockets between processes this will haunt you unless you are
> aware of it. The cool thing about it as that you get automatic
> "resource reclamation" because of this. It also happens with files
> (they are closed), ETS tables, and so on.
>
>


-- 
============================================================
Ivan A. Uemlianin
Speech Technology Research and Development

                     ivan@REDACTED
                      www.llaisdy.com
                          llaisdy.wordpress.com
                      www.linkedin.com/in/ivanuemlianin

     "Froh, froh! Wie seine Sonnen, seine Sonnen fliegen"
                      (Schiller, Beethoven)
============================================================



More information about the erlang-questions mailing list