[erlang-questions] gen_tcp not correctly handling half duplex(shutdown) sockets?
Scott Parish
srp@REDACTED
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