开发者

How to prevent "The connection was reset" error?

I have a very basic TCP server implemented in Ruby. In general it does what it's supposed to, but every once in a while I get "The connection to the server was reset while the page was loading" error. I have a feeling that it has something to do with close terminating the con开发者_运维百科nection too soon. If so, how do I wait for all the data to be sent? Or is it something else?

require 'socket'

server = TCPServer.new('', 80)
loop do
    session = server.accept
    begin
        session.print Time.now
    ensure
        session.close
    end
end


I'm not an expert in this area, but here is what I believe is happening....

The browser sends a GET request with the header field "Connection: keep-alive". So the browser is expecting to keep the connection alive at least until it receives a complete chunk of the response. Under this protocol, the server response must include a header specifying the length of the response, so that the browser knows when it has received the complete response. After this point, the connection can be closed without the browser caring.

The original example closes the connection too quickly, before the browser can validate that a complete response was received. Curiously, if I run that example and refresh my browser several times, it will load about every 1 in 10 tries. Maybe this erratic behavior is due to the browser occasionally executing fast enough to beat my server closing the connection.

Below is a code example that executes consistently in my browser:

require 'socket'

response = %{HTTP/1.1 200 OK
Content-Type: text;charset=utf-8
Content-Length: 12

Hello World!
}

server = TCPServer.open(80)

loop do
  client = server.accept
  client.puts response
  sleep 1
  client.close
end


I suspect it's because the browser is expecting an HTTP response with headers &c. Curiously, you can make the "reset" error happen every time if you put before the "ensure" a sleep of, say, one second.

How to fix it depends upon what you are after. If this is not to be an HTTP server, then don't use the browser to test it. Instead, use telnet or write a little program. If it is to be an HTTP server, then take a look at webrick, which is built into Ruby MRI >= 1.8. Here's how:

#!/usr/bin/ruby1.8

require 'webrick'

# This class handles time requests

class TimeServer < WEBrick::HTTPServlet::AbstractServlet

  def do_GET(request, response)
    response.status = 200
    response['Content-Type'] = 'text/plain'
    response.body = Time.now.to_s
  end

end

# Create the server.  There are many other options, if you need them.
server = WEBrick::HTTPServer.new(:Port=>8080)

# Whenever a request comes in for the root page, use TimeServer to handle it
server.mount('/', TimeServer)

# Finally, start the server.  Does not normally return.
server.start


Also, should note that including Connection: close in the response header doesn't seem to help me at all with this connection reset error in my browser (FFv3.6). I have to include both the content-length header field, and include the sleep method to put some delay in the connection closing in order to get a consistent response in my browser.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜