I have a defect that I don't fully understand. When I dispatch something by gen_tcp:send(...), I follow through with :close(). However, there's a sporadic pattern of the data getting cut off early. If I inject a delay between them, the problem disappears.
This seems to imply that :close() can close a socket which is still sending data. That isn't what I would have expected by comparison from other languages, so I'm not entirely convinced I've understood this correctly.
Is it safe to call :close() immediately after a large :send()? If not, what does one do instead?
________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org
There are two buffers between you and the wire. First there is the Socket/Port buffer and then there is the operating system socket buffer.
When you send data from Erlang the data that could not be transmitted directly is queued for delivery when more kernel buffer space is available.
After you issue a gen_tcp:close then if the server side is really slow and do not process any data for more than 5 seconds then the socket is closed any way. My guess is that you send some buffer that is queued in the operating system buffer and then you call close. What happens then is up to the tcp implementation. Are you using Windows ?
The "safe" way to terminate a sending socket is to use shutdown(S, write) and then wait for the server side to close the connection. The shutdown interface will also wait until all data queued in the Port/socket is written to the operating system socket before issuing the low level shutdown.
> I have a defect that I don't fully understand. When I dispatch > something by gen_tcp:send(...), I follow through with :close(). > However, there's a sporadic pattern of the data getting cut off early. > If I inject a delay between them, the problem disappears.
> This seems to imply that :close() can close a socket which is still > sending data. That isn't what I would have expected by comparison > from other languages, so I'm not entirely convinced I've understood > this correctly.
> Is it safe to call :close() immediately after a large :send()? If > not, what does one do instead?
> After you issue a gen_tcp:close then if the server side is really slow and > do not process any data for more than 5 seconds then the socket is closed any way.
It's lightning fast by design. Having Erlang's excellent mature timeslicer to work with has made it borderline trivial to make a webserver that's fast enough to send Marty McFly back in time.
You heard me: my webserver goes 88 miles an hour.
> My guess is that you send some buffer that is queued in the operating system > buffer and then you call close.
Well right now I'm just testing over localhost. Same machine for server and client.
> What happens then is up to the tcp implementation. Are you > using Windows ?
This happens both under Vista Home Premium 64 and Gentoo 64.
> The "safe" way to terminate a sending socket is to use shutdown(S, write) > and then wait for the server side to close the connection.
This here may be exactly what I need to know. To check, first, though: in context, erlang _is_ the server side. Does that change things? The client is any web browser. I apologize for having been unclear.
> The shutdown interface will also wait until all data queued in the > Port/socket is written to the > operating system socket before issuing the low level shutdown.
See, that's what I would have expected. Windows doesn't close sockets with outbound data on them, when you're writing C/C++. That right there is a big part of why I'm worried I haven't yet correctly diagnosed the problem.
> Hope this will lead you forward.
I suspect it has, but my being unclear about Erlang's role as a server suggests I need to make sure I didn't actually present a wrong situation for advice first.
________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org
>> The "safe" way to terminate a sending socket is to use shutdown(S, >> write) >> and then wait for the server side to close the connection.
> This here may be exactly what I need to know. To check, first, > though: in context, erlang _is_ the server side. Does that change > things? The client is any web browser. I apologize for having been > unclear.
Then perhaps you should check the exit_on_close option in the inet module. If the client uses shutdown you will be able to write data to the client and then close after this is done.
The issue is that, conceptually, what needs to happen is the server should provide a response then drop as soon as its response is completely dispatched. Erlang is not waiting for the other side to close. Erlang is completely in control here. The desired behavior is solely guided by when that gen_tcp:send(...) is complete.
It's a webserver. The client doesn't close the connection.
On Sun, Jun 14, 2009 at 4:48 PM, Tony Rogvall<t...@rogvall.se> wrote:
> The "safe" way to terminate a sending socket is to use shutdown(S, write)
> and then wait for the server side to close the connection.
> This here may be exactly what I need to know. To check, first, > though: in context, erlang _is_ the server side. Does that change > things? The client is any web browser. I apologize for having been > unclear.
> Then perhaps you should check the exit_on_close option in the inet module. > If the client uses shutdown you will be able to write data to the client and > then close after this is done. > /Tony
________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org
> The issue is that, conceptually, what needs to happen is the server > should provide a response then drop as soon as its response is > completely dispatched. Erlang is not waiting for the other side to > close. Erlang is completely in control here. The desired behavior is > solely guided by when that gen_tcp:send(...) is complete.
> It's a webserver. The client doesn't close the connection.
> On Sun, Jun 14, 2009 at 4:48 PM, Tony Rogvall<t...@rogvall.se> wrote:
>> The "safe" way to terminate a sending socket is to use shutdown(S, >> write)
>> and then wait for the server side to close the connection.
>> This here may be exactly what I need to know. To check, first, >> though: in context, erlang _is_ the server side. Does that change >> things? The client is any web browser. I apologize for having been >> unclear.
>> Then perhaps you should check the exit_on_close option in the inet >> module. >> If the client uses shutdown you will be able to write data to the >> client and >> then close after this is done. >> /Tony