Curious behaviour of gen_tcp

Alexis Le-Quoc <>
Tue Jan 30 23:54:08 CET 2001


Hello everyone,

I'm using the following program structure to have an erlang process
communicate with a socket based server (written in perl). The code is
simplified on purpose.

start() ->
  loop_idle().

loop_idle(Queue)
  case not_empty(Queue) of
    true ->
      send_and_loop(Queue);
    _ ->
      do_nothing
  end;

  receive
    {send, Data} ->
      send_and_loop(Data);
    _ ->
      log_crap
  end.

send_and_loop(Queue) ->
  {ok, Socket} = gen_tcp:connect("localhost", 1, [binary, {packet, 0}]),
  gen_tcp:send(Socket, Queue:pop()),
  loop_busy(Queue, Socket, <<>>).

loop_busy(Queue, Socket, Buffer) ->
  receive
    {tcp, Socket, Data} ->
      loop_busy(Socket, concat_binary([Buffer, Data]);
    {tcp_closed, Socket} ->
      io:fwrite("Finished ~w", [length(binary_to_list(Buffer)]),
      loop_idle(Queue);
    Any ->
      io:fwrite("Received ~w~n", [Any])
  end.

%%%%%%%%%%%%%

This works great except that for responses bigger than 70 KB, I don't get
consistent results, i.e. sometimes, the response received by erlang is
about the right size (compared to what was sent by the server, always the
same size), sometimes, it's half or a quarter of the size.

Am I correct in assuming that the {tcp_closed..} pattern does not
necessarily match after {tcp, Socket, Data}? I.e. the process will match
some {tcp, Socket, Data} and then, if {tcp_closed...} has been received,
it *can* match it and exit the loop *while* there are still {tcp, Socket,
Data} messages in its mailbox.

If this is correct, does it mean that I need to spawn a listener process
which will do gen_tcp:recv() and notify the parent that it has received
all data?

I have to say I'm a bit boggled by this one.

Alexis




More information about the erlang-questions mailing list