I'm pretty new in Ruby and I'm trying to implement Threading, but now I've got a mistake: client doesn't understand that connection has been closed.
Earlier, I wrote a simple tcp client-server app in C++, and the application works correct: if the server closed the connection, the client says that connection was closed too. But in Ruby nothing (as a client) happens and than the application exits with errors:
main.rb:34:in `write': Broken pipe (Errno::EPIPE)
from main.rb:34:in `puts'
from main.rb:34:in `block (2 levels) in send'
from main.rb:32:in `loop'
from main.rb:32:in `block in send'
So, here is the part of the source file of the C++ app. As you can see, if iResult
equals 0
it means that the server has closed the connection.
if (iResult > 0) {
std::string recievedString(recvbuf, recvbuf + iResult);
std::cout << recievedString;
}
else if (iResult == 0) {
std::cout << "Connection closed." << std::endl;
break;
}
And it works fine.
There is Ruby server-client tcp apps:
CLIENT APP Yeah, sorry for these stupid methods..
#!/usr/bin/env ruby -w
require "socket"
class Client
def initialize( server )
@server = server
@request = nil
@response = nil
listen
send
@request.join
@response.join
end
def listen
@response = Thread.new do
loop {
msg = @server.gets.chomp
if msg == ""
Thread.kill(@request)
Thread.kill(@response)
else
puts msg
end
}
end
end
def send
puts "Enter the username:"
@request = Thread.new do
loop {
msg = $stdin.gets.chomp
@server.puts( msg )
}
end
end
end
server = TCPSocket.open( "127.0.0.1", 6666 )
Client.new( server )
SERVER APP
#!/usr/bin/env ruby -w
require "socket"
class Server
def initialize( port, ip )
@server = TCPServer.open( ip, port )
@connections = Hash.new
@clients = Hash.new
@connections[:server] = @server
@connections[:clients] = @clients
run
end
def run
loop {
Thread.start(@server.accept) do | client |
nick_name = client.gets.chomp.to_sym
puts nick_name
@connections[:clients][nick_name] = client
puts @connections.inspect
client.puts "0001"
listen_user_messages(nick_name, client)
client.close
Thread.kill self
end
}
end
def listen_user_messages( username, client )
loop {
msg = client.gets.chomp
if msg == "0002"
command = "Yah, two"
else
command = "Go home"
end
client.puts command
break
}
end
end
Server.new( 6666, "127.0.0.1")
When a TCPSocket object is closed, calls to .gets
will return nil
. That means that your @server.gets.chomp
will raise an error ( NoMethodError
) and the thread will terminate. To handle this case, you want to check the return value of the socket's .gets
call.
def listen
@response = Thread.new do
loop {
msg = @server.gets
if msg.nil?
Thread.kill(@request)
Thread.kill(@response)
else
puts msg.chomp
end
}
end
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.