我有一个利用赛璐珞进行网络并行的工作脚本。它的作用是扫描一系列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
答案 0 :(得分:1)
我想我知道问题所在。你看,puts不是线程安全的。当你调用puts时,它会做两件事:a)它打印你想要的任何东西到屏幕上b)它在最后插入一个换行符\ n。所以一个线程(线程A)可以执行a)但是然后停止并且另一个线程(线程B)也可以执行a),然后操作系统可能再次转到线程A,这将执行b)等,从而产生输入你看到了。
所以解决方案是用“打印你想要的任何东西”来替换所有的放置实例。例如,这个:
puts "#{@host} Firewalled!"
可以转换为:
print "#{@host} Firewalled!\n"
与puts不同,print是线程安全的,在完成之前不能被打断。