TCPServer bug?

Y

Yan Bernatsky

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
 
R

Robert Klemme

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?

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
 
Y

Yan Bernatsky

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.
 
R

Robert Klemme

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
 
A

Ammar Ali

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
 
Y

Yan Bernatsky

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?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,962
Messages
2,570,134
Members
46,692
Latest member
JenniferTi

Latest Threads

Top