[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