Project

General

Profile

Feature #14736 ยป port_scanner_threadlet.rb

normalperson (Eric Wong), 06/13/2018 01:03 AM

 
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