赛璐珞输出乱序并且格式不规律

时间:2014-09-24 21:41:06

标签: ruby

我有一个利用赛璐珞进行网络并行的工作脚本。它的作用是扫描一系列IP地址并尝试连接它们。它将输出ip_addr:Filtered,Refused或Connected。脚本的唯一问题是打印结果的方式。而不是按顺序排列,如下:

192.168.0.20: Filtered 192.168.0.21: Connected

输出如下:

192.168.0.65 Firewalled! 192.168.0.11 Firewalled!192.168.0.183 Firewalled!192.168.0.28 Firewalled!192.168.0.171 Firewalled!192.168.0.228 Firewalled! 192.168.0.238 Firewalled!192.168.0.85 Firewalled!192.168.0.148 Firewalled!192.168.0.154 Firewalled!192.168.0.76 Firewalled!192.168.0.115 Firewalled!

192.168.0.215 Firewalled!

在终端。正如你所看到的那样,它完全不稳定。这是相关代码:

    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(@port, addr[0][3]))

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

        if resp.nil?
            puts "#{@host} Firewalled!"
        end

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

        rescue Errno::ECONNREFUSED
            puts "#{@host} Refused!"

        rescue
            false
        end
    end
    sock
end

range = []
main = Ranger.new(ARGV[0], ARGV[1])


(1..254).each do |oct|
    range << main.strplace(ARGV[0]+oct.to_s)
end


threads = []

range.each do |ip|
    threads << Thread.new do
        scan = Ranger.new(ip, ARGV[1])
        scan.future :connect
    end
end

threads.each do |thread|
    thread.join
end

1 个答案:

答案 0 :(得分:1)

我想我知道问题所在。你看,puts不是线程安全的。当你调用puts时,它会做两件事:a)它打印你想要的任何东西到屏幕上b)它在最后插入一个换行符\ n。所以一个线程(线程A)可以执行a)但是然后停止并且另一个线程(线程B)也可以执行a),然后操作系统可能再次转到线程A,这将执行b)等,从而产生输入你看到了。

所以解决方案是用“打印你想要的任何东西”来替换所有的放置实例。例如,这个:

puts "#{@host} Firewalled!"

可以转换为:

print "#{@host} Firewalled!\n"

与puts不同,print是线程安全的,在完成之前不能被打断。