Simple port scanner in Python 3 I wrote a simple python port scanner today and I would like to get some advice on how to improve on the code in different ways.

I am aware that I can implement threading to reduce runtime but I won't for now as it feels a bit advanced at this time. Rather I would like tips/opinions on how to improve the program in other ways.

You can find the code on my GitHub.

I am aware that the logging is a bit redundant as it doesn't log anything now, I simply forgot to remove it.

# Network port scanner
# Focus first will be on making the functionality of the software.
# Second focus will be on lowering the runtime of the software.


import socket
import logging
import time


class SConnect:

    def __init__(self, ip, port=None):
        self.ip = ip
        self.port = port
        self.address = (self.ip, self.port)
        self.s_connection = socket.socket(socket.AF_INET,       socket.SOCK_STREAM)
        self.s_connection.settimeout(0.3)

    def portscan(self):

        return self.s_connection.connect_ex(self.address)


def main():

    logging.basicConfig(filename="errlog.log", format="%(asctime)s : %(message)s")
    logging.info("Start")
    print("\nHello user and welcome to Network Port Scanner!")
    print("Please insert a IP address that you want to scan for open and     closed ports.")
    print("The range of ports scanned is 1-65535.")
    u_ip = input("\nTarget IP: ")

    open_pcounter = 0
    closed_pcounter = 0

    if u_ip is not None:
        for p in range(1, 65536):
            start_ptime = time.time()
            c = SConnect(u_ip, p)
            if c.portscan() == 0:
                print("Port {} is open".format(p))
                open_pcounter += 1
            else:
                print("Port {} is closed".format(p))
                closed_pcounter += 1
            print("--- %s seconds ---" % (time.time() - start_ptime))
    else:
        print("You failed, terminating.\n")

    print("Total open ports:%s".format(open_pcounter))
    print("Total closed ports:%s".format(closed_pcounter))
    logging.info("Finished")


if __name__ == '__main__':
    start_time = time.time()
    main()
    print("--- %s seconds ---" % (time.time() - start_time))
Connections

You don't close your sockets and connections. The best way to ensure you close them is with a context manager (with-statement)

You can also reuse the socket you make, and connect it to other ports. This would make a SocketConnection:

class SocketConnection:
    def init(self, ip, port=None):
        self.socket = None
        self.ip = ip    

    def __enter__(self):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def __exit__(self, type, value, traceback):
        self.socket.close()
        self.socket = None

    def portscan(self, port):
        if self.socket is None:
            raise ConnectionError('No socket open')
        try:
            return not self.socket.connect_ex((self.ip, port))
        finally:
            self.socket.detach()


This can be used like this:

def scan_ports(ip, port_range):
    """yields the open ports in `port_range` (port_range is half-open) """
    with SocketConnection(ip) as connection:
        for port in range(*ports):
            if connection.portscan(port):
                yield port


Validate input

You don't validate the input of your client. To do this, you can do something like this:

def validate_ip(ip):
    return True # needs implementation
def get_ip():
    while True:
        ip = input("Target IP: ")
        if validate_ip(ip):
            return ip


You can do ctrl+C to get out of this while True loop

and then the main() function:

def main():
    logging.basicConfig(filename="errlog.log", format="%(asctime)s : %(message)s")
    logging.info("Start")
    message = """
    Hello user and welcome to Network Port Scanner!
    Please insert a IP address that you want to scan for open and closed ports.
    The range of ports scanned is 1-65535.
    """
    print(message)
    ip = get_ip()
    open_ports = list(scan_ports(ip, (1, 65536)))

    print(
        f"""open ports: ({len(open_ports)})
        {open_ports}""")


Caveat: I don't know a lot about socket programming. I just used the python documentation, so there might be socket-related bugs