user3674736
user3674736

Reputation: 69

Closing socket doesn't work in Ruby

I am attempting to create a better port scanner by implementing more error handling, and I've run into a bit of trouble.

    def pscan(host_name, port)
        begin
            sock = Socket.new(:INET, :STREAM)
            raw = Socket.sockaddr_in(port, host_name)
            if sock.connect(raw)
                puts "Port #{port} is up!"
            rescue (Errno::ECONNREFUSED)
                false
            rescue (Errno::ETIMEDOUT)
                puts "Port #{port} timed out!"
      end
end

def run
    port = 1
    begin
        while port <= ARGV[1].to_i do
            popen(ARGV[0], port)
            port += 1
        end

        rescue (Errno::EHOSTUNREACH)
                puts "No path to host"

        rescue(Interrupt)
            puts " Process interrupted"
    end
end


run

The trouble is that for each port scanned, it will print "No path to host", instead of printing that once and then closing the socket. I'm clearly doing it wrong but everywhere online I find simple code closes a socket connection this way.

Upvotes: 0

Views: 303

Answers (2)

josh
josh

Reputation: 10318

Like you mentioned in your comments and your code changes, you would have to move the socket closing into the block that's calling your code rather than inside of that code itself, since the block of code will continuously call the method and the socket will never actually be closed.

You'll basically have to do what you posted in your code:

require 'socket'

def pscan(host_name, port)
  begin
  sock = Socket.new(:INET, :STREAM)
  raw = Socket.sockaddr_in(port, host_name)
  if sock.connect(raw)
    puts "Port #{port} is up!"
  end
  rescue (Errno::ECONNREFUSED)
    puts "Connection refused to port #{port}"
    false
  rescue (Errno::ETIMEDOUT)
    puts "Port #{port} timed out!"
    false
  end
end

def run
  puts "Attempting to scan host #{ARGV[0]}"
  port = 1
  begin
  while port <= ARGV[1].to_i do
    pscan(ARGV[0], port)
    port += 1
  end
  rescue (Errno::EHOSTUNREACH)
    puts "No path to host #{ARVG[0]}"
  rescue(Interrupt)
    puts "Process interrupted"
  end
end

run

Some thoughts: you may not always get "No path to host" errors when running your code; when I tested it in my network, I never got a "No path to host" error but always got a "Port ... timed out!" error even when I tested it against known unreachable hosts such as 10.0.0.1. You'll have to be wary of that when you run your code in other networks as you might get different results.

Upvotes: 0

max
max

Reputation: 10454

I think that you forgot to close the if statement. Also, use 'ensure' to close it. Try this:

def pscan(host_name, port)
    begin
    sock = Socket.new(:INET, :STREAM)
    raw = Socket.sockaddr_in(port, host_name)
    if sock.connect(raw)
        puts "Port #{port} is up!"
    end

    rescue (Errno::ECONNREFUSED)
        false
    rescue (Errno::ETIMEDOUT)
        puts "Port #{port} timed out!"
    rescue (Errno::EHOSTUNREACH)
        puts "No path to host"
    ensure
        sock.close
    end
end

Upvotes: 1

Related Questions