2014-09-24 44 views
0

我目前有一个用Ruby编写的脚本,它扫描一系列IP地址并尝试连接到它们。目前速度非常缓慢。在网络上扫描254台主机需要长达300秒的时间,这显然不太实际。我想要做的是给脚本一些并发,希望加快脚本。到目前为止,这是我的:我一定是误解赛璐珞

require 'socket' 
require 'celluloid' 

$res_arr = [] 


class Ranger 
include Celluloid 

def initialize(host) 
    @host = host 
    @timeout = 1 
end 


def ip_range(host) 
    host =~ /(?:\d{1,3}\.){3}[xX*]{1,3}/ 
end 


def ctrl(host) 
    begin 

     if ip_range(host) 
      strIP = host.gsub(/[xX*]/, '') 

      (1..254).each do |oct| 
       $res_arr << strIP+oct.to_s 
      end 
     else 
      puts "Invalid host!" 
     end 

    rescue 
     puts "onnection terminated." 
    end 
end 

def connect 
    addr = Socket.getaddrinfo(@host, nil) 
    sock = Socket.new(Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0) 


    begin 
     sock.connect_nonblock(Socket.pack_sockaddr_in(22, addr[0][3])) 

    rescue Errno::EINPROGRESS 
     resp = IO.select(nil, [sock], nil, @timeout.to_i) 

     if resp.nil? 
      $res_arr << "#{@host} Firewalled!" 
     end 

     begin 
      if sock.connect_nonblock(Socket.pack_sockaddr_in(22, addr[0][3])) 
       $res_arr << "#{@host}Connected!" 
      end 

     rescue Errno::ECONNREFUSED 
      $res_arr << "#{@host} Refused!" 

     rescue 
      false 
     end 
    end 
    sock 
end 


def output(contents) 
    puts contents.value 
end 


end # Ranger 

main = Ranger.new(ARGV[0]) 
main.ctrl(ARGV[0]) 

$res_arr.each do |ip| 
    scan = Ranger.new(ip) 
    scnftr = scan.future :connect 
    scan.output(scnftr) 
end 

该脚本的作品,但它只需要在我包括赛璐珞的时候一样长。我是否误解赛璐珞的工作原理以及它应该怎么做?

回答

1

你的问题是你的循环的每个迭代开始一个未来,然后立即等待它返回一个值。你想要什么,而不是开始是所有期货,然后等待所有期货在两个单独的步骤完成:

futures = $res_arr.map do |ip| 
    scan = Ranger.new(ip) 
    scan.future :connect 
end 

# now that all futures are running, we can start 
# waiting for the first one to finish 

futures.each do |future| 
    puts future.value 
end 

下面是赛璐珞源又如:https://github.com/celluloid/celluloid/blob/master/examples/simple_pmap.rb

+0

对不起,我有点困惑,我没有在您的代码中看到scnftr的定义。另外第二个模块会抛出错误,并且关于扫描的错误未定义。 – user3408678 2014-09-24 06:34:10

+0

对不起。第一个问题是一个错字,它在第二个块中必须是'future'而不是'scnftr'。第二个问题是'scan'没有被定义。不过,我认为你可以抛弃'输出'的方法,它在课堂上无关紧要!它不以任何方式使用该实例。相反,直接写'puts future.value'即可。编辑我的答案。 – 2014-09-24 07:39:34

+0

谢谢你这样做。这是非常非常接近工作。脚本现在速度更快,这是此主题的重点。唯一的问题是输出的格式。我的脚本准确地输出每个主机,以及它是否打开,关闭或过滤。麻烦的是,它将所有这些都按顺序输出 - 首先显示的是打开的主机,而不是按照IP顺序排列。此外,混合适当的输出是一堆这些:#<套接字:0x000000017c6540>。我如何摆脱这些? – user3408678 2014-09-24 17:24:07