gen_tcp:recv - last segement when closed port

jmT2 johan@REDACTED
Sat Mar 11 20:28:15 CET 2006


> Do you get a different result with that code? What version of Erlang/OTP
> are you running?

  V 5.4.13

I downloaded the latest. To see if it did any difference.


> Tcpdumping the traffic, I see that this code results in
> the FIN coming in its own packet rather than being "piggybacked" on the
> last data packet, which may be different from your case and could
> possibly be relevant - can you check that?

Hmmm, my FIN bit is actually piggybacked on the last HTTP continuation! In  
the Ethereal trace it is then immediately acked by my client.

I've tried to reconstruct the senario with the tcpbug. Tried to set  
{dealy_send, true} on the server so that the last 1199 bytes should be  
buffered and only sent when the socket was closed. Hmm, try the below, I  
get the wriong reply every fifth run:

The server is sending one packet with 1500 bytes, the reciever has a  
recbuf of 100 bytes (don't know how important this is nor why I get 1024  
bytes in the first read).

8>tcpbug:cli(3481).
Got 1024 bytes
Got {error,closed}
ok
9> tcpbug:cli(3483).
Got 1024 bytes
Got 476 bytes
Got {error,closed}
ok
10> tcpbug:cli(3485).
Got 1024 bytes
Got 476 bytes
Got {error,closed}
ok
11> tcpbug:cli(3487).
Got 1024 bytes
Got {error,closed}
ok
12> tcpbug:cli(3489).
Got 1024 bytes
Got 476 bytes
Got {error,closed}
ok
13> tcpbug:cli(3491).
Got 1024 bytes
Got 476 bytes
Got {error,closed}
ok
14> tcpbug:cli(3493).
Got 1024 bytes
Got {error,closed}
ok
15>

8<------------------------------------------------------------------------

-module(tcpbug).

-export([srv/0, cli/1]).


srv() ->
     {ok, S} = gen_tcp:listen(0, [{delay_send, true}]),
     {ok, P} = inet:port(S),
     io:format("Listen port: ~w~n", [P]),
     srv_loop(S).

srv_loop(S) ->
     {ok, A} = gen_tcp:accept(S),
     gen_tcp:send(A, lists:duplicate(1500, $A)),
     gen_tcp:close(A).


cli(P) ->
     {ok, S} = gen_tcp:connect("localhost", P,
  			      [list, {recbuf, 100}, {packet,0}, {active, false}]),
     cli_loop(S).

cli_loop(S) ->
      case gen_tcp:recv(S, 0, 40000) of
	{ok, L} ->
  	    io:format("Got ~w bytes~n", [length(L)]),
	    sleep(500),   % parsing...
  	    cli_loop(S);
  	R ->
  	    io:format("Got ~p~n", [R])
      end,
      gen_tcp:close(S).

sleep(T) ->
      receive
      after T ->
  	    ok
      end.





-----------
Johan Montelius jmT2



More information about the erlang-questions mailing list