套接字模块 (python) 工作但不使用指定的端口号?

Socket module (python) works but doesn't use specified port number?

我正在使用 Python 3.7 中的 socket 模块(应该没关系,因为我尝试从不同的 venv 激活不同的 Python 版本)。

问题是我创建了一个监听端口 65432 的 TCP 连接,这是我为这个简单演示选择的任意数字。

server.py 如下所示:

import socket

HOST = '127.0.0.1' # Standard loopback interface address (localhost)
PORT = 65432 # Non-privileged ports are > 1024

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen() 
    conn, addr = s.accept() 
    with conn:
        print('Connected by', addr)
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)

client.py 相对简单,因为它与 127.0.0.1:65432 建立连接。

import socket

HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 65432 # Port used by the server

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    # Send its message and then read the server's reply and prints it
    s.sendall(b'Hello, world')
    data = s.recv(1024)

print('Received', repr(data))

执行 server.py 打开端口 65432 进行监听(在第一个控制台中),然后执行 client.py 发送一个简单的 'hello world' 消息(在第二个控制台中)。这是打印到第一个控制台的内容:

Connected by ('127.0.0.1', 56051)

到目前为止一切顺利。端口 56051 连接到端口 65432,对吗?没有。

我执行 netstat -am(用于查看主机上套接字状态的命令工具实用程序)并发现:

Active Internet connections (including servers)
Proto Recv-Q Send-Q  Local Address          Foreign Address        (state)    
tcp4       0      0  127.0.0.1.51495        *.*                    LISTEN 

而不是 127.0.0.1.65432 作为本地地址,而是使用端口 51495。

进行另一次验证检查,这次启动 lsof -i -n:

COMMAND     PID     FD   TYPE             DEVICE SIZE/OFF NODE NAME
Code\x20H 51214    37u  IPv4 0x1af15eb424ba89f3      0t0  TCP 127.0.0.1:51495 (LISTEN)

两次验证均确认正在使用端口 51495 而不是我的 server.pyclient.py 脚本中指定的 65432。任何线索或提示?非常感谢!

65432 是您的服务器套接字的端口号,而不是您的客户端套接字。由于客户端没有附加任何特定的端口号,它会动态分配端口号,每次你 运行 客户端代码。 据我了解,您提到了 -

Connected by ('127.0.0.1', 56051)

显示在您的服务器控制台的第一个控制台上。所以这个端口号是客户端套接字的端口号。不是服务器套接字。

在服务器代码中,您正在使用 s.accept(),此函数 returns 连接临时 ID 和发出请求的客户端地址。与您尝试在代码中打印的内容相同。

正如@ottomeister 所指出的,流程名称是第一个赠品。进程名本应是Python却显示VS Code,说明51495端口是VS Code进程打开的,与我们的socket模块代码无关

上下文管理器的设置方式意味着连接将在最后一行(在本例中为 socket.sendall())执行时关闭。所以服务器套接字不再活动。

I 运行 netstat 客户端套接字连接后,此时服务器端口已关闭。

当我在服务器端口打开时(在客户端套接字与其连接之前)监视端口状态时,果然出现了 65432。 netstatlsofnmap 都证实了这一点。套接字连接成功后的简单打印语句也将确认服务器端口实际上正在使用指定的端口号,即65432。

对于给您带来的不便,我们深表歉意,再次感谢 Ottomeister 首先指出这一点。