0

我有一个小脚本,它扫描端口 411 上从 192.168.190.xxx 到 192.168.220.xxx 的所有 ip。

该脚本有时工作正常,但有时我收到错误“没有可用的缓冲区空间” dcport.rb:8:in初始化':没有可用的缓冲区空间 - 连接(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
4

1 回答 1

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
于 2012-09-03T20:09:24.473 回答