Подтвердить что ты не робот

Открыть открытый TCP-порт в Python

Я хочу получить произвольный открытый TCP-порт на localhost в Python. Что является самым простым способом?

4b9b3361

Ответ 1

Мое текущее решение:

def get_open_port():
        import socket
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(("",0))
        s.listen(1)
        port = s.getsockname()[1]
        s.close()
        return port

Не очень приятный, а также не 100% правильный, но он работает пока.

Ответ 2

Я действительно использую следующее в одной из моих программ:

port = random.randint(10000,60000)

Конечно, это даже больше подвержено столкновениям, чем у кода, который у вас есть. Но у меня никогда не было проблем с этим. Дело в том, что в любой момент времени большинство из этих портов с высоким номером не используются, и если вы просто выбираете один случайным образом, конфликт с другим процессом довольно маловероятен. Если вы сделаете что-то вроде решения, которое вы отправили в своем ответе (открытие сокета и захват его номера порта), он почти уверен, что порт не будет конфликтовать. Поэтому, если это то, что вы будете использовать только для себя (в отличие от того, что вы собираетесь публиковать), подумайте о том, стоит ли покупать действительно пуленепробиваемое решение. Скорее всего, это никогда не изменит ситуацию.

Мотивированный комментарием Марсело Кантоса на ваш вопрос, я добавлю, что стандартное решение в таких случаях - это процесс, который будет использовать привязку порта к нему, а затем поделиться этой информацией с любой другой программой, которая ему нужна., Обычно он будет делать что-то вроде записи временного файла, содержащего номер порта, в какое-то стандартное место в файловой системе. Поскольку процесс, с которым вы работаете, не делает этого, в каком-то смысле любое решение, которое вы придумали, будет немного взломанным. Но опять же, если это только для вашего собственного использования, это, вероятно, прекрасно.

Ответ 3

Свободный порт можно найти, привязав сокет к порту, выбранному операционной системой. После того, как операционная система выбирает порт, гнездо может быть удалено. Однако это решение не устойчиво к условиям гонки - за короткое время между получением номера бесплатного порта и использованием этого порта другой процесс может использовать этот порт.

def find_free_port():
    s = socket.socket()
    s.bind(('', 0))            # Bind to a free port provided by the host.
    return s.getsockname()[1]  # Return the port number assigned.

Ответ 4

Это моя версия, однако она не является случайной, если вы укажете диапазон портов. Это также будет страдать от условий гонки, но это лучший способ, который я знаю, если вам нужно знать порт раньше времени.

import socket
import errno
import contextlib

reserved_ports = set()

def get_open_port(lowest_port = 0, highest_port = None, bind_address = '', *socket_args, **socket_kwargs):
    if highest_port is None:
        highest_port = lowest_port + 100
    while lowest_port < highest_port:
        if lowest_port not in reserved_ports:
            try:
                with contextlib.closing(socket.socket(*socket_args, **socket_kwargs)) as my_socket:
                    my_socket.bind((bind_address, lowest_port))
                    this_port = my_socket.getsockname()[1]
                    reserved_ports.add(this_port)
                    return this_port
            except socket.error as error:
                if not error.errno == errno.EADDRINUSE:
                    raise
                assert not lowest_port == 0
                reserved_ports.add(lowest_port)
        lowest_port += 1
    raise Exception('Could not find open port')

Ответ 5

Эфемерные порты в основном лежат в диапазоне 49152 - 65535. если вы хотите проверить порты в большем диапазоне, просто измените значения в randint.

import pustil
from random import randint
def getfreeport():
    port = randint(49152,65535)
    portsinuse=[]
    while True:
        conns = pstuil.net_connections()
        for conn in conns:
            portsinuse.append(con.laddr[1])
        if port in portsinuse:
            port = randint(49152,65535)
        else:
            break
    return port