Feature #14736 ยป port_scanner_threadlet.rb
1 |
#!/usr/bin/env ruby
|
---|---|
2 |
require 'socket' |
3 |
|
4 |
class PortScanner |
5 |
def initialize(host: '0.0.0.0', ports:, batch_size: 1024) |
6 |
@host = host |
7 |
@ports = ports.to_a |
8 |
@batch_size = batch_size |
9 |
end
|
10 |
|
11 |
def scan_port(port, timeout) |
12 |
peer = Socket.tcp(@host, port, connect_timeout: timeout) |
13 |
puts "#{port} #{peer.wait_writable(timeout) ? 'open' : 'timeout'}" |
14 |
peer.close |
15 |
rescue Errno::ECONNREFUSED |
16 |
# puts "#{port} closed"
|
17 |
rescue SystemCallError => e |
18 |
puts "#{port} #{e.message}" |
19 |
end
|
20 |
|
21 |
def start(timeout = 1.0) |
22 |
@batch_size.times.map do |
23 |
Threadlet.start do |
24 |
while port = @ports.shift |
25 |
scan_port(port, timeout) |
26 |
end
|
27 |
end
|
28 |
end.each(&:join) |
29 |
end
|
30 |
end
|
31 |
|
32 |
limits = Process.getrlimit(Process::RLIMIT_NOFILE) |
33 |
batch_size = [512, limits.first].min |
34 |
host = "127.0.0.1" |
35 |
scanner = PortScanner.new(host: host, ports: Range.new(1, 65535), batch_size: batch_size) |
36 |
|
37 |
scanner.start |