Domanda

Voglio ottenere qualsiasi casuale aprire la porta TCP su localhost in Python.Che cosa è il modo più semplice?

È stato utile?

Soluzione

La mia soluzione attuale:

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

Non è molto bello e, inoltre, non corretta al 100%, ma funziona per il momento.

Altri suggerimenti

Il porto libero possono essere trovati attraverso l'associazione di un socket ad una porta selezionata dal sistema operativo.Dopo che il sistema operativo seleziona una porta la presa può essere smaltiti.Tuttavia, questa soluzione non è resistente alle condizioni di gara - nel breve tempo tra ottenere il numero di porta libero e utilizzando questa porta altro processo può utilizzare questa porta.

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.

Io in realtà uso la seguente uno dei miei programmi:

port = random.randint(10000,60000)

Naturalmente, questo è anche più inclini a collisioni di codice.Ma non ho mai avuto un problema con esso.Il punto è che, in qualsiasi momento, la maggior parte di quelli ad alta numerata porte non sono in uso, e se vi basta scegliere uno a caso, di avere un conflitto con un altro processo è abbastanza improbabile.Se si fa qualcosa che piace la soluzione che hai postato la tua risposta (l'apertura di un socket e afferrando il suo numero di porta), è quasi certo che il porto non ha intenzione di conflitto.Quindi, se questo è qualcosa che sarà solo per te (in contrapposizione a qualcosa che si sta andando a rilasciare al pubblico), pensa se vale la pena di venire fino con una vera prova di proiettile soluzione.Le probabilità sono mai fare la differenza.

Motivati da Marcelo Cantos " commenta la tua domanda, vorrei aggiungere che la soluzione standard in casi come questo è il processo che utilizza la porta si legano ad essa e condividere informazioni con qualsiasi altro programma che lo richiede.In genere si metterà a fare qualcosa come la scrittura di un file temporaneo che contiene il numero di porta standard posizione nel filesystem.Poiché il processo si sta lavorando non riesce a farlo, in un certo senso, qualunque sia la soluzione che si arriva con un po ' di un hack.Ma ancora, se è solo per il vostro uso, che è probabilmente bene.

Questa è la mia versione, ma non è davvero casuale se si specifica un intervallo di porte. Questo sarà anche soffrono di condizioni di gara, ma questo è il modo migliore che conosco, se avete bisogno di sapere il porto prima del tempo.

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')

Le porte temporanee fondamentalmente trovano nel range tra 49152 - 65535. se si desidera controllare i porti in grande gamma poi basta cambiare i valori in 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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top