Hello all. I been messing around with this port scanner for a while now and can't wrap my head around the speed issue. I tried to create a few threads to help speed it up, but I'm pretty sure I havn't made any progress. Could someone explain why the speed is so slow, and why the threads I created still run in succesion and not at the same time to speed the process up. Any help or suggestions would be greatly appreciated.

import socket
from threading import Thread


class scanner(object):
    address = "127.0.0.1"
    port = 0
    def __init__(self):
        scan1 = Thread(None, self.r1to100())
        scan1.start()
        scan2 = Thread(None, self.r100to200())
        scan2.start()
    
        
    def r1to100(self):
        for x in range(1, 100):
            print("checking port " + str(x) + " on " + self.address)
            check = self.scan_server(self.address, x)
            if check == True:
                print("scan_server returned " + str(check))
                print()
            else:
                pass

    def r100to200(self):
        for x in range(100, 200):
            print("checking port " + str(x) + " on " + self.address)
            check = self.scan_server2(self.address, x)
            if check == True:
                print("scan_server returned " + str(check))
                print()
            else:
                pass


    
    def scan_server(self, address, port):
        s = socket.socket() 
        #print("Attempting to connect to " + address + " on port " + str(port)) 
        try: 
            s.connect((address, port)) 
            print("Connected to server " + address +  " on self.port " + str(port))
            return True 
        except socket.error: 
            #print("Connecting to " + address + " on port " +  str(port) + " failed")
            return False

    def scan_server2(self, address, port):
        s = socket.socket() 
        #print("Attempting to connect to " + address + " on port " + str(port)) 
        try: 
            s.connect((address, port)) 
            print("Connected to server " + address +  " on port " + str(port))
            return True 
        except socket.error: 
            #print("Connecting to " + address + " on port " +  str(port) + " failed")
            return False


scan = scanner()

Not sure why your version is running slowly. Here's a quick and dirty version I just came up with using threads and a queue. It runs very quickly for me (less than a second I'd guess).

import socket
import threading
import Queue
import time

class Worker(threading.Thread):
    def __init__(self, port_queue):
        threading.Thread.__init__(self)
        self.port_queue = port_queue
        
    def run(self):
        while True:
            item = self.port_queue.get()
            
            if item is False:
                break
            
            address, port = item
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

            try:
                s.connect((address, port))
            except socket.error:
                print "%d: down" % port
                continue
            
            print "%d: up" % port
            s.close()

if __name__ == "__main__":
    port_queue = Queue.Queue()
    num_threads = 4
    
    # Create worker threads and start them
    for i in range(0, num_threads):
        Worker(port_queue).start()

    # Add all the ports to scan to the queue
    for i in range(1, 201):
        port_queue.put(('localhost', i))

    # Finally add False once for each thread so that they will stop
    for i in range(0, num_threads):
        port_queue.put(False)

    # Just sit here doing nothing until nothing is left in the queue
    while port_queue.qsize() != 0:
        time.sleep(.1)

Yeah looks pretty nice for just throwing it together, I tried runnin it on py3 but it crashes for some reason. Maybe something diffrent than the version you are running, I'll definatly check out the queue module though.

Yeah looks pretty nice for just throwing it together, I tried runnin it on py3 but it crashes for some reason. Maybe something diffrent than the version you are running, I'll definatly check out the queue module though.

Yea, I'm running 2.5. To make it work in py3 just change "Queue" to "queue" on line 3, "Queue.Queue()" to "queue.Queue()" on line 31, and the "print" commands on lines 24 and 27 need to be functions (just wrap the args in parenthesis).

@willygstyle. Perhaps you should try your first code with arguments to socket.socket() . I'm not sure it will be any better, but calling socket without arguments is unusual.

Yep I tried making those ajustments. It looked like those were the only things diffrent in the versions, but it still crashes whenever I try to use queue. Not sure why its not wanting to play nice with that module, never had any programs crash like this before.

Well I got some interesting results with a version that uses threads only. I did some searching around on google and found one that works really good. I think I have somwhat of an idea what the problem is. It seems that while the threads are doing their thing, idle goes a little haywire.

import socket
import threading
from threading import Thread

MAX_THREADS = 100

    
class Scanner(Thread):
    def __init__(self, host, port):
        Thread.__init__(self)
        # host and port
        self.host = host
        self.port = port
        # build up the socket obj
        self.socket = socket.socket()

    def run(self):
        try:
            # connect to the given host:port
            self.socket.connect((self.host, self.port))
            print(self.host + " " + str(self.port) + " open")
            self.socket.close()
        except:
            pass



    def scan(self, host, start, stop):
        self.port = start
        while self.port <= stop:
            while threading.activeCount() < MAX_THREADS:
                Scanner(host, self.port).start()
                self.port += 1
        
if __name__ == "__main__":
    blah = Scanner("localhost", 0)
    blah.run()
    blah.scan("localhost", 1, 200)

If I run this just as it is, it's fine. But if I print results from the except clause instead of just letting it run past it, python spews a bunch of crap at idle and crashes it. It will run in the console but, without a newline charecter that even gets very messy.

This article has been dead for over six months. Start a new discussion instead.