在ruby中防止“没有可用的缓冲区空间”错误

时间:2012-09-03 19:54:55

标签: ruby sockets error-handling

我有一个小脚本,扫描端口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

1 个答案:

答案 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