从客户端查找选择哪个端口的最佳方法

Best way to find which port is selected from client-side

我的程序使用地址 ('0.0.0.0', 0) 随机选择一个端口服务器端,并将唯一的 code 发送到客户端,套接字试图连接到一个范围内的每个端口,并且检查相同的 code 以确认正确的服务器端口。

问题是遍历所有端口 (range(1024, 65336)),即使使用 ThreadPool,尝试连接到每个端口也非常慢。


这只是一个展示我正在尝试做的事情的例子。我的主程序通过互联网托管,而不是在本地主机上。

server.py

import socket 

CODE = 'Code123' # just an example

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
addr = ('0.0.0.0', 0)
server.bind(addr)

# Can see which port is assigned
print(server)

def start():
    server.listen(5) # connect to 5 connection.
    while True:
        conn, addr = server.accept()
        conn.send(CODE.encode('utf-8'))
        print("Code Sent")

start()

cilent.py

import socket
from multiprocessing.pool import ThreadPool

code = 'Code123' # just an example
server = socket.gethostbyname(socket.gethostname())
port_left = 65336
found = False

def connect(port):
    global port_left, code, server, found
    if found: return
    port_left -= 1
    try:
        client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        client.connect((server, port))
        if client.recv(len(code)).decode('utf-8') == code:
            found = True
            return client
        else: client.close()
    except Exception as e:
        print(e, port_left)
    return None

pool = ThreadPool(10)
values = [('c', i) for i in set(pool.map(connect, range(1024, 65336))) if i]
client = dict(values).get('c')
pool.close()
pool.join()
print(client)

有没有更好的方法来实现这个目标或提高我现有代码的性能?

nmap provides ways to do this. Here's the example code from this page:

import nmap 

# take the range of ports to  
# be scanned 
begin = 75
end = 80

# assign the target ip to be scanned to 
# a variable 
target = '127.0.0.1'

# instantiate a PortScanner object 
scanner = nmap.PortScanner() 

for i in range(begin,end+1): 

    # scan the target port 
    res = scanner.scan(target,str(i)) 

    # the result is a dictionary containing  
    # several information we only need to 
    # check if the port is opened or closed 
    # so we will access only that information  
    # in the dictionary 
    res = res['scan'][target]['tcp'][i]['state'] 

    print(f'port {i} is {res}.') 

输出:

port 75 is closed.
port 76 is closed.
port 77 is closed.
port 78 is closed.
port 79 is closed.
port 80 is open.

但是,我会说随机分配服务器端口是不切实际的,您最好只分配一个固定端口。

不是直接回答,但太长了无法发表评论。

这不是预期使用随机端口的方式。它们用于 FTP 协议中的数据连接方式(被动模式):

  • 客户端在已知端口 (21) 上打开控制连接
  • 它向服务器请求随机数据端口通过控制连接
  • 它打开数据连接知道它的端口

应避免在随机端口上打开连接,因为如果服务器没有立即响应,客户端必须等待超时以决定服务器是否正忙。

因此,如果您想使用随机端口,我的建议是保留一个众所周知的端口,客户端将在该端口上获得真正的随机端口。