Skip to content

Instantly share code, notes, and snippets.

@Cyanoxygen
Last active September 20, 2020 01:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Cyanoxygen/64938614406508aa1ee0db266d2625e8 to your computer and use it in GitHub Desktop.
Save Cyanoxygen/64938614406508aa1ee0db266d2625e8 to your computer and use it in GitHub Desktop.
Port tester in Python with socket

Description

NOTE: These two errnos used in this script may only functional in Windows. You need to modify this script before using this script in *nix systems.

This simple file will allow you to test if a port is available for usage. I recently found that some ports can not be used beacuse of insufficient permission. I wrote this simple script to test how many ports are blocked by sofware firewall installed in my PC. After some search I discovered that it's all Hyper-V's fault. Stop reserving ports, Hyper-V.

Usage

Just simply invoke a Python 3.6+ to run this script.

It will test all available ports (1025-65535) by trying to bind to 0.0.0.0. It will give you a simplified report after testing.

Related links

https://stackoverflow.com/a/54727281
docker/for-win#3171 (comment)

"""
A simple port tester, using socket to bind and see what will happen.
WTFPL
"""
import sys
import socket
import itertools
import errno
available_ports = (1025, 65535)
used_ports = []
failed_ports = []
success_ports = []
host = '0.0.0.0'
def ranges(i):
"""
Generate a range from list of numbers
Source: https://stackoverflow.com/a/4629241
"""
for a, b in itertools.groupby(enumerate(i), lambda pair: pair[1] - pair[0]):
b = list(b)
pair = b[0][1], b[-1][1]
if pair[0] == pair[1]:
yield (pair[0])
else:
yield pair
def try_bind(port: int) -> int:
"""
Try to bind a port using socket.
Returns 0 if successfully bind, 1 if the port is used, otherwise returns 2.
"""
status = 0
print(f'Testing port {port}...', end='\r')
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind((host, port))
except socket.error as e:
if e.errno == errno.WSAEACCES:
failed_ports.append(port)
status = 2
return status
elif e.errno == errno.WSAEADDRINUSE:
used_ports.append(port)
status = 1
return status
else:
print(f'\nPort {port} is in a unknown status.')
return 3
success_ports.append(port)
s.close()
return status
def printout_ranges(r: list):
counter = 0
for i in r:
str = ''
if counter > 80:
print()
counter = 0
if type(i) is int:
str += '{} '.format(i)
else:
str += '{}-{} '.format(i[0], i[1])
counter += len(str)
print(str, end='')
print()
def printout():
print('\r')
range_s = list(ranges(success_ports))
range_f = list(ranges(failed_ports))
range_i = list(ranges(used_ports))
print(f'You have {len(success_ports)} ports available.')
print('These ports are:')
printout_ranges(range_s)
print()
print(f'You have {len(used_ports)} ports which are already in use.')
print('These ports are:')
printout_ranges(range_i)
print()
print(f'You have {len(failed_ports)} ports which can NOT be bound.')
print(f'If you have WSL 2 or Hyper-V enabled, head to the link below for more details:')
print('https://github.com/docker/for-win/issues/3171#issuecomment-459205576')
print('https://stackoverflow.com/a/54727281')
print('These ports are:')
printout_ranges(range_f)
if __name__ == "__main__":
print(f'Testing port from {available_ports[0]} to {available_ports[1]} ...')
for i in range(available_ports[0], available_ports[1] + 1):
try_bind(i)
printout()
sys.exit(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment