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?
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
···
On 27.10.2010 17:05, Yan Bernatsky wrote:
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?
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.
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?
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.
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.
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.