我有一个Ruby TCPSocket客户端,除非我试图关闭它,否则效果很好。当我在下面的代码中调用 disconnect 方法时,我收到此错误:
./smartlinc.rb:70:in `start_listen': stream closed (IOError)
from ./smartlinc.rb:132:in `initialize'
from ./smartlinc.rb:132:in `new'
from ./smartlinc.rb:132:in `start_listen'
from bot.rb:45:in `initialize'
from bot.rb:223:in `new'
from bot.rb:223
这是(简化)代码:
class Smartlinc
def initialize
@socket = TCPSocket.new(HOST, PORT)
end
def disconnect
@socket.close
end
def start_listen
# Listen on a background thread
th = Thread.new do
Thread.current.abort_on_exception = true
# Listen for Ctrl-C and disconnect socket gracefully.
Kernel.trap('INT') do
self.disconnect
exit
end
while true
ready = IO.select([@socket])
readable = ready[0]
readable.each do |soc|
if soc == @socket
buf = @socket.recv_nonblock(1024)
if buf.length == 0
puts "The socket connection is dead. Exiting."
exit
else
puts "Received Message"
end
end
end # end each
end # end while
end # end thread
end # end message callback
end
有没有办法可以阻止或发现这个错误?我不是套接字编程方面的专家(很明显!),所以非常感谢所有帮助。
答案 0 :(得分:2)
你的线程坐在IO.select()
,而陷阱代码用@socket.close
高兴地猛击门,因此你得到了一些抱怨。
不要将abort_on_exception设置为true,或者在代码中正确处理异常:
这些方面的东西......
Kernel.trap('INT') do
@interrupted = true
disconnect
exit
end
...
ready = nil
begin
ready = IO.select(...)
rescue IOError
if @interrupted
puts "Interrupted, we're outta here..."
exit
end
# Else it was a genuine IOError caused by something else, so propagate it up..
raise
end
...