[erlang-questions] Difference in 'close' for gen_tcp recv vs. active
Fred Hebert
mononcqc@REDACTED
Wed Apr 9 02:49:12 CEST 2014
The difference here is that we have a peer that actively closes the
connection and the packets are readable and detected as far as tcpdumps
go. Things like FINs or RSTs. They're making it to our host, they're
just entirely ignored unless we're willing to read undefined amounts of
data from the buffer for the stack to apparently get access to them.
99.99% of the time that's gonna be 0 bytes because of HTTP clients' rare
tendency to pipeline requests.
I'm just extremely annoyed having to figure out a way to add in a buffer
to carry possibly unlimited amounts of data to read from a socket so it
can figure out if a FIN or RST was sent recently, but I guess that's the
way we'll have to do it.
Oh well.
On 04/08, Garret Smith wrote:
> 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
> >
More information about the erlang-questions
mailing list