Forum: Ruby TCPServer bug?

757fb0d5ec7560b6f25f5bd98eadc020?d=identicon&s=25 Jan Bernacki (yan_bernatsky)
on 2010-10-27 17:05
Hello.
I have a problem with TCP server like this

require "socket"
server = TCPServer.open(2000)
loop do
  Thread.start(server.accept) do |client|
    while msg = client.gets
      sleep 10
      client.puts "bye"
    end
  end
end

While server sleep if client breaking connection (hard break), server
becomes invalid: he can accept connections, but can not puts to client
any data and no exceptions return.
Ruby 1.9.2
What is happened?

*sorry for my english
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2010-10-27 18:25
(Received via mailing list)
On 27.10.2010 17:05, Yan Bernatsky wrote:
>    end
> end
>
> While server sleep if client breaking connection (hard break), server
> becomes invalid: he can accept connections, but can not puts to client
> any data and no exceptions return.
> Ruby 1.9.2
> What is happened?

You'll probably do not see the exception because you do not catch and
handle it.  Try Thread.abort_on_exception = true at the beginning of the
script to at least see the error.

Kind regards

  robert
757fb0d5ec7560b6f25f5bd98eadc020?d=identicon&s=25 Jan Bernacki (yan_bernatsky)
on 2010-10-28 10:12
Thank you, Robert.

I have an exception "Connection reset by peer" now and server continue
to works for another clients. But client, who break the connection,
can't connect to server again.
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2010-10-28 10:24
(Received via mailing list)
On Thu, Oct 28, 2010 at 10:12 AM, Yan Bernatsky <releu@me.com> wrote:
> I have an exception "Connection reset by peer" now and server continue
> to works for another clients. But client, who break the connection,
> can't connect to server again.

That's most likely an issue in your client code.

Cheers

robert
34339790bbfb524b877a79d8af706e9c?d=identicon&s=25 Ammar Ali (ammar)
on 2010-10-28 12:10
(Received via mailing list)
On Thu, Oct 28, 2010 at 11:24 AM, Robert Klemme
<shortcutter@googlemail.com> wrote:
> On Thu, Oct 28, 2010 at 10:12 AM, Yan Bernatsky <releu@me.com> wrote:
>> I have an exception "Connection reset by peer" now and server continue
>> to works for another clients. But client, who break the connection,
>> can't connect to server again.
>
> That's most likely an issue in your client code.

Hi Yan,

If the client can reconnect after a few minutes (5 or so, depending on
OS), then you might need to set the socket option SO_REUSEADDR using
setsockopt before connecting.

  client_socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1
)

HTH,
Ammar
757fb0d5ec7560b6f25f5bd98eadc020?d=identicon&s=25 Jan Bernacki (yan_bernatsky)
on 2010-11-02 15:35
This server is included into Rails app and initialized after
Application.initialize!

module Game
  class Server
    def initialize!
      Thread.abort_on_exception = true
      server = TCPServer.open(2000)
      Thread.new do
        begin
          loop do
            socket = server.accept
            Game::Client.new(socket) if socket
          end
        rescue => e
          puts "WARNING: #{e}"
        end
      end
    rescue => e
      puts "FATAL: #{e}"
    end
  end

  class Client
    include Response
    Actions = {}
    def initialize(client)
      puts "$ new client"
      @client = client
      Thread.abort_on_exception = true
      @mem = MemCache.new('localhost:11211')
      @user_id = nil
      Thread.new do
        while msg = @client.gets
          response_for_message(msg)
          sleep 2
        end
      end
      processing_user_events
    end

    private

    def processing_user_events
     # ...
    end

    def response_for_message(msg)
      puts "$$ start response_for_message"
      msg = msg.to_s.strip
      #puts "rqs: #{msg[0..80]}"
      case msg
      when "close" then
        @client.close
        puts "$ client close by message"
      else
        id, key, query = msg.split("#")
        response = get_response(id, key, query)
        response = "error: bad request" unless response
        send(response)
      end
    rescue => e
      puts "ERROR: #{e}"
      @client.close
      puts "$ client close"
    ensure
      puts "$$ end response_for_message"
    end

    def send(response)
      puts "$$$ start send"
      Timeout.timeout 5 do
        @client.puts response.to_s + "\0"
        #puts "rsp: #{response[0..80]}"
      end
    rescue => e
      puts "ERROR: #{e}"
      @client.close
      puts "INFO: client close"
    ensure
      puts "$$$ end send"
    end

    def get_response(id, key, query = "")
      puts "$$$ start get_response"
      params = {}
      CGI.parse(query.to_s).each_pair do |k, v|
        unless k.blank? and v.blank?
          params[k.to_sym] = v.first.to_s.strip
        end
      end
      puts "$$$$ 1"
      user = User.find_by_key(key.to_s.strip)
      puts "$$$$ 2"
      @user_id = user.id if user
      puts "$$$$ 3"
      if user.confirm
        puts "$$$$ 4"
        begin
          puts "$$$$ 5"
          puts "$$$$ start controllers"
          query = Actions[id.to_i]
          raise "Action not found" unless query
          query[:params].merge!(params)
          # ... => response
        rescue => e
          puts "ERROR: #{e};"
        ensure
          puts "$$$$ end controllers"
        end
      end
    rescue => e
      puts "ERROR: #{e}"
    ensure
      puts "$$$ end get_response"
    end
  end
end


debug:
$ new client
$$ start response_for_message
$$$ start get_response
$$$$ 1
$$$$ 2
$$$$ 3
$$$$ 4
$$$$ 5
$$$$ start controllers
$$$$ end controllers
$$$ end get_response
$$$ start send
$$$ end send
$$ end response_for_message
[2010-11-02 16:09:38] ERROR Errno::ECONNRESET: Connection reset by peer
  /Users/releu/Sites/mobile_wars/config/initializers/game_server.rb:57:in
`gets'
$ new client
$$ start response_for_message
$$$ start get_response
$$$$ 1
After this Rails is not responding for any clients.
What I missed?
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.