Forum: Ruby TCPServer bug?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
E138e1fa66a2be844efeb1369868cccb?d=identicon&s=25 Jan B. (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
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
E138e1fa66a2be844efeb1369868cccb?d=identicon&s=25 Jan B. (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.
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
3476844cc7d395a22cb91881eda4bfe3?d=identicon&s=25 Ammar A. (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
E138e1fa66a2be844efeb1369868cccb?d=identicon&s=25 Jan B. (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?
This topic is locked and can not be replied to.