[erlang-questions] Difference in 'close' for gen_tcp recv vs. active
Garret Smith
garret.smith@REDACTED
Wed Apr 9 01:25:23 CEST 2014
Basically, this has everything to do with TCP sockets (and the OS
implementation) and very little to do with Erlang. I do get {error,
closed} from gen_tcp:send when the client disconnects. I'm running
R16B03-1 on FreeBSD 10.
Here are some decent descriptions of the problem:
http://www.linuxquestions.org/questions/programming-9/how-could-server-detect-closed-client-socket-using-tcp-and-c-824615/
The second answer in the page above has some good links too, pulled out for
easy reference:
http://stackoverflow.com/questions/722240/instantly-detect-client-disconnection-from-server-socket
http://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-2.html#ss2.8
-Garret
On Tue, Apr 8, 2014 at 1:40 PM, Fred Hebert <mononcqc@REDACTED> wrote:
> Hi there,
>
> Happy fun case we're hitting on nodes using Erlang right now. We have an
> HTTP proxy that does direct data streaming from a server to a client.
> This is done through a series of recv from the server, and of sends to
> the client. The TCP sockets involved are all in passive mode.
>
> The problem with this approach is that because this is a purely
> unidirectional stream until the server says so or the client quits, we'd
> like to detect both of these events.
>
> The server quitting or being done is easy enough, but the client
> quitting cannot be detected, apparently.
>
> It turns out that gen_tcp:send/2 always returns 'ok' even if the
> connection has been closed by the peer before. Erlang/OTP just won't
> acknowledge the fact unless someone tries to read from the socket,
> either through gen_tcp:recv or by using inet:setopts(Port, [{active,
> once}]), at which point {error, closed} starts being returned by
> gen_tcp:send/2. This happens, even if `{exit_on_close, true}` is
> specified as an option.
>
> The question I have here is why is this behavior different for send than
> recv. It seems that `gen_tcp:send` will happily wait for hours
> pretending to send data (no matter the timeout values used are), even
> once the connection has been closed by the other peer.
>
> Is there any way for me to detect that a connection has been closed
> without possibly having to poll `recv` on each packet I try to send (and
> then may need to buffer all that data, which I'd prefer to avoid) or
> changing the entire app's workflow to be active?
>
> In case, here are the socket options we use:
>
> [{active,false},
> {broadcast,false},
> {buffer,1460},
> {delay_send,false},
> {dontroute,false},
> {exit_on_close,true},
> {header,0},
> {high_watermark,8192},
> {keepalive,false},
> {linger,{false,0}},
> {low_watermark,4096},
> {mode,binary},
> {nodelay,true},
> {packet,0},
> {packet_size,0},
> {priority,0},
> {recbuf,87380},
> {reuseaddr,true},
> {send_timeout,infinity},
> {sndbuf,65536}]
>
> Regards,
> Fred.
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20140408/c35dca35/attachment.htm>
More information about the erlang-questions
mailing list