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

时间:2020-05-26 13:19:46

标签: python sockets networking multiprocessing threadpool

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

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


这仅是显示我正在尝试执行的操作的示例。我的主程序通过Internet而不是localhost托管。

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)

是否有更好的方法来实现这一目标或改善现有代码的性能?

2 个答案:

答案 0 :(得分:4)

不是直接的答案,但是评论太久了。

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

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

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

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

答案 1 :(得分:0)

nmap提供了执行此操作的方法。以下是this page中的示例代码:

for

输出:

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

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