TCPServer bug?

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

On 27.10.2010 17:05, Yan B. 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

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.

On Thu, Oct 28, 2010 at 10:12 AM, Yan B. [email protected] 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

On Thu, Oct 28, 2010 at 11:24 AM, Robert K.
[email protected] wrote:

On Thu, Oct 28, 2010 at 10:12 AM, Yan B. [email protected] 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

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?