题
我想获得在Python本地主机的任何随机打开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)
当然,这是更容易受到碰撞比你的代码。但我从来没有遇到过问题的。问题的关键是,在任何给定的时间,大多数那些高编号端口的未使用的,如果你只是随机挑选一个,其与另一个进程冲突是非常不可能的。如果你这样做,你在你的答案贴在溶液(打开插座,抓住它的端口号),这是几乎可以肯定,端口不会发生冲突。因此,如果这是什么,你只能使用自己(而不是东西,你打算向公众发布),想想它的价值是否会来了一个真正的防弹解决方案。奇怪的是它永远不会有所作为。
这是对您的问题马塞洛诗章评论的推动下,我会补充说,在这样的情况下,标准的解决方案是有一个将要使用的端口绑定到它,然后分享给任何需要它的其他程序,信息化进程。通常它会做这样的事情写包含端口号到文件系统中的一些标准位置的临时文件。既然你正在使用的过程中没有做到这一点,在某种意义上,任何解决方案,你想出将成为黑客攻击的一位。但同样,如果它只是供自己使用,这可能是罚款。
这如果指定一个端口范围是我的版本,但它不是一个真正随机的。这也将遭受竞争条件,但是这是我所知道的最好的方式,如果你需要提前知道时间的端口。
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 - 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
不隶属于 StackOverflow