Cela trouvera un port aléatoire dans la plage donnée:
import socket
import random
from typing import Tuple
def find_listening_port(
port_range:Tuple[int,int]=None,
host='',
socket_type='tcp',
default:int=None
) -> int:
"""Trouver un port d'écoute disponible
Arguments:
port_range: Tuple optionnel des ports à rechercher aléatoirement, ``[min_port, max_port]``
Si omis, rechercher aléatoirement entre ``[6000, 65534]``
host: Interface hôte à rechercher, si omise alors se lier à toutes les interfaces
socket_type: Le type de socket, cela devrait être ``tcp`` ou ``udp``
default: Le port à essayer en premier avant de rechercher aléatoirement dans la plage des ports
Renvoie:
Port disponible pour l'écoute
"""
def _test_port(host, port, socket_protocol):
with socket.socket(socket.AF_INET, socket_protocol) as sock:
try:
sock.bind((host, port))
if socket_type == 'tcp':
sock.listen(1)
return port
except:
pass
return -1
if port_range is None:
port_range = (6000,65534)
if socket_type == 'tcp':
socket_protocol = socket.SOCK_STREAM
elif socket_type == 'udp':
socket_protocol = socket.SOCK_DGRAM
else:
raise Exception('Argument socket_type invalide, doit être: tcp ou udp')
searched_ports = []
if default is not None:
port = _test_port(host, default, socket_protocol)
if port != -1:
return port
searched_ports.append(default)
for _ in range(100):
port = random.randint(port_range[0], port_range[1])
if port in searched_ports:
continue
port = _test_port(host, port, socket_protocol)
if port != -1:
return port
searched_ports.append(port)
raise Exception(f'Impossible de trouver un port d\'écoute {socket_type} pour l\'hôte={host}')
Exemple d'utilisation:
# Trouver un port TCP,
# vérifier d'abord si le port 80 est disponible
port = find_listening_port(
port_range=(4000, 60000),
host='',
socket_type='tcp',
default=80
)
print(f'Port TCP disponible: {port}')