Hi, I’m experimenting an annoying issue when a server disconnects a TCP
connection established by a Ruby client.
Let me start with an example of what I consider the expected behavior:
a) Using Linux “telnet” command:
- First connect to google.com:
~$ telnet google.com 80
Trying 209.85.229.106…
Connected to google.com.
Escape character is ‘^]’.
-
Then write something (“hello\n”):
hello
-
So I receive a 400 response:
HTTP/1.0 400 Bad Request
[…] -
And a warning:
“Connection closed by foreign host.”
-
telnet exits with status 1 due to the remote disconnection error.
b) Using Ruby 1.9.1 TCPSocket:
-
First connect:
irb> require “socket”
true
irb> socket = TCPSocket.new(“google.com”, 80)
#TCPSocket:0x00000001010288 -
Now netstat shows the connection as ESTABLISHED (ok).
-
Write “hello\n” into the socket:
irb> socket.puts “hello”
nil -
I receive the same 400 response from the www server. Now netstat shows
the
connection as CLOSE_WAIT (OK?). -
Write “hello\n” again (IMHO it should fail):
irb> socket.puts “hello”
nil <---- didn’t raise !!! -
Doing a ngrep I see that irb has sent “hello\n” over the previous TCP
connection but this time it doesn’t receive response from the www
server. This
is, irb is using a closed connection!:T 2010/01/12 20:12:04.072705 192.168.1.10:35272 → 209.85.229.105:80
[AP]
hello -
But after this new “puts” now netstat shows nothing! (no connection =>
OK). -
Repeat again:
irb> socket.puts “hello”
Errno::EPIPE: Broken pipe
from (irb):6:inwrite' from (irb):6:in
puts’
from (irb):6
from /usr/bin/irb:12:in `’ -
Now it raises!
Why didn’t Ruby raise in the second “puts” attemp??? the server already
closed
the connection! Why does Ruby realize of it after a new retry?
Well, this issue causes one request lost (the second one) since there is
no
way to know if the server accepted or dropped the request.
Is it a bug? is there a way to check the socket connection before
sending
(loosing in fact) a request? (TCPSocket#closed? is not valid here as it
just
returns true in case we have closed a socket).
Thanks a lot for any help.