[erlang-questions] gen_tcp not correctly handling half duplex(shutdown) sockets?

Scott Parish <>
Thu Dec 20 06:41:50 CET 2007


Nice! Thanks for the info; apologies for not reading the  
documentation carefully enough

sRp

On Dec 19, 2007, at 4:08 PM, Paulo Sérgio Almeida wrote:

> Hi,
>
> to be able to keep sending after the other side has made a half- 
> close you need to pass {exit_on_close, false} while creating the  
> listening socket.
>
> I include an example that works (at least with "active" sockets).  
> This "adder" server keeps adding numbers received until the client  
> half-closes the connection, and then replies with the sum of all  
> numbers received so far.
>
> Regards,
> psa
>
> P.S. In case someone has spare time to comment ... does my code use  
> binaries efficiently assuming R12B?
>
> Scott R Parish wrote:
>> Its not clear to me if i'm doing something wrong, or if gen_tcp isn't
>> correctly handling half duplex sockets. As a refresher, half duplex
>> sockets are created when shutdown(2) is called on a socket to  
>> close one
>> direction:
>>   http://www.softlab.ntua.gr/facilities/documentation/unix/unix- 
>> socket-faq/unix-socket-faq-2.html#ss2.6
>> My erlang code is acting as follows:
>> maple% erl
>> Erlang (BEAM) emulator version 5.5.5 [source] [async-threads:0]  
>> [hipe]
>> [kernel-poll:false]
>> Eshell V5.5.5  (abort with ^G)
>> 1> Opts = [binary, {packet, raw}, {active, false}].
>> [binary,{packet,raw},{active,false}]
>> 2> {ok, LS} = gen_tcp:listen(6000, Opts).
>
> -module(adder).
> -export([client/2, client/3, server/1]).
>
> client(Port, List) ->
>   client("localhost", Port, List).
> client(Host, Port, List) ->
>   {ok, Sock} = gen_tcp:connect(Host, Port, [binary]),
>   [ok = gen_tcp:send(Sock, <<I:32>>) || I <- List],
>   gen_tcp:shutdown(Sock, write),
>   receive {tcp, Sock, <<J:32>>} ->
>     receive {tcp_closed, Sock} -> ok = gen_tcp:close(Sock), J end
>   end.
>
> server(Port) ->
>   {ok, LSock} = gen_tcp:listen(Port, [{exit_on_close, false},  
> binary]),
>   acceptor(LSock, 0).
>
> acceptor(LSock, Sum) ->
>   {ok, Sock} = gen_tcp:accept(LSock),
>   io:format("new client~n", []),
>   NewSum = serve(Sock, Sum, <<>>),
>   acceptor(LSock, NewSum).
>
> serve(Sock, Sum, Buffer) ->
>   receive
>     {tcp, _, Data} ->
>       {NewSum, NewBuffer} = handle(Sum, <<Buffer/binary, Data/ 
> binary>>),
>       serve(Sock, NewSum, NewBuffer);
>     {tcp_closed, Sock} ->
>       io:format("client disconnected~n", []),
>       ok = gen_tcp:send(Sock, <<Sum:32>>),
>       ok = gen_tcp:close(Sock),
>       Sum;
>     {tcp_error, Sock, _} ->
>       io:format("tcp error~n", []),
>       Sum
>   end.
>
> handle(Sum, <<I:32, R/binary>>) -> handle(I + Sum, R);
> handle(Sum, Buf) -> {Sum, Buf}.
>




More information about the erlang-questions mailing list