質問
私は、Pythonのlocalhost上の任意のランダムなオープンTCPポートを取得したいです。最も簡単な方法は何ですか?
解決
私の現在のソリューション:
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%正確ではないが、それは今のために働くわけではありません。
他のヒント
空きポートがオペレーティングシステムによって選択されたポートにソケットを結合することによって求めることができます。オペレーティングシステムがポートを選択した後、ソケットを配置することができます。しかし、この解決策は、競合条件に耐性ではありません - 空きポート番号を取得して、このポートの他のプロセスを使用しての間の短い時間で、このポートを使用することができます。
。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.
私は実際に私のプログラムの一つで、次を使用します:
port = random.randint(10000,60000)
もちろん、これはさらに多くなりやすいあなたが持っているコードよりも衝突にあります。しかし、私はそれで問題を抱えていたことがありません。ポイントは、任意の時点で、それらの高い番号のポートのほとんどが使用されていないし、あなただけランダムに1つを選ぶ場合は、他のプロセスとの競合を持つことはかなり可能性は低いです。あなたはあなたの答えに投稿された溶液(ソケットをオープンし、そのポート番号をつかん)のような何かを行う場合は、ポートが競合するつもりはないことはほぼ確実です。これは、あなたが自分だけのために使用されますことを何か(あなたはしているが、公衆にリリースする予定のものではなく)であれば、それの価値が本当に防弾ソリューションを考え出すかどうかを考えます。オッズは、それが違いを生むことは決してないだろうされます。
あなたの質問にマルセロ・カントスはコメントが動機、私はこのようなケースでは標準溶液がそれにポートバインドを使用するプロセスを持っているし、それを必要とする他のプログラムでその情報を共有することであることを追加します。通常、これはファイルシステム内のいくつかの標準的な場所にポート番号を含む一時ファイルの書き込みのようなものをやります。あなたが作業しているプロセスがそれをしないので、どのような解決策いくつかの意味であなたはハックのビットになります思い付きます。それはあなた自身の使用のためだけだ場合しかし、再び、それはおそらく大丈夫です。
これは、ポート範囲を指定した場合しかし、その本当にランダムではなく、私のバージョンです。また、これは競合状態に苦しむだろうが、これはあなたが事前にポートを知る必要がある場合、私が知っている最良の方法です。
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')
エフェメラルポートは基本的範囲49152にあります。 あなたがより大きな範囲のポートをチェックしたいならば、ちょうど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