我一定是误解了赛璐珞

时间:2014-09-24 03:21:24

标签: ruby

我目前有一个用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

该脚本可以工作,但它需要的时间与我之前的Celluloid一样长。我是否误解了赛璐珞的作用以及它应该做什么?

1 个答案:

答案 0 :(得分: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