我有一个小脚本,扫描端口411上从192.168.190.xxx到192.168.220.xxx的所有ips。
脚本有时工作正常,但有时我会收到错误“没有可用的缓冲区空间”
dcport.rb:8:in
初始化':没有可用的缓冲区空间 - connect(2)(Errno :: ENOBUFS)`
我已经读过,当套接字未正确关闭时会发生这种情况,但我使用mysocket.close
来防止我认为无法正常工作。
如何防止这种情况发生,我的意思是如何正确关闭插座?
我的代码如下
require 'socket'
require 'timeout'
(190...216).each do |i|
(0...255).each do |j|
begin
#puts "Scanning 192.168.#{i}.#{j}"
scan=Timeout::timeout(10/1000.0) {
s=TCPSocket.new("192.168.#{i}.#{j}",411)
s.close
puts "192.168.#{i}.#{j} => Hub running"
}
rescue Timeout::Error
rescue Errno::ENETUNREACH
rescue Errno::ECONNREFUSED
end
end
end
答案 0 :(得分:2)
我的猜测是,有时候,套接字创建和套接字关闭之间的超时会触发,这会让你泄漏一些套接字。因为(据快速谷歌搜索告诉我),ENOBUFS在1024个套接字打开后默认发生,这肯定是它。
超时,以及Thread.raise,在你需要确定某些事情发生的情况下(在你的情况下,s.close)是非常有害的,因为你实际上不能再保证它了:异常可以在任何地方提出,即使在确保区内。
在你的情况下,我认为你可以通过在超时块中添加一个在外面来修复它(未经测试的代码如下):
require 'socket'
require 'timeout'
(190...216).each do |i|
(0...255).each do |j|
begin
#puts "Scanning 192.168.#{i}.#{j}"
s = nil
scan=Timeout::timeout(10/1000.0) do
s=TCPSocket.new("192.168.#{i}.#{j}",411)
puts "192.168.#{i}.#{j} => Hub running"
end
rescue Timeout::Error
rescue Errno::ENETUNREACH
rescue Errno::ECONNREFUSED
ensure
s.close if s
end
end
end