Python套接字NAT端口地址

Python socket NAT port address

我在 NAT 后面有一个客户端套接字,我想获取进程使用的本地端口号。

为了说明我的问题,这里有一个简单的例子。

假设我使用以下代码创建了一个服务器:

welcome_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
welcome_socket.bind(("", 1500))
welcome_socket.listen(5)

然后我监听传入的连接:

(client_socket, address) = self.welcome_socket.accept()

我使用以下代码从客户端(在 NAT 后面)连接:

sock = socket.create_connection(("server_address", 1500))

这是我有点困惑的地方。

我在服务器端获得的地址包含客户端连接到的 WiFi 网络的 public 地址(我期望)和一些端口号,根据我对 NAT 的理解,应该是与客户端实际使用的端口号不同,用于地址转换。

但是,如果我在客户端使用 getsockname() 函数,我得到的端口号与服务器提供的端口号相同。

返回代码中的示例。

在服务器上:

client_socket.getpeername()
>>> ('WiFi_address', 4551)

在客户端上:

sock.getsockname()
>>> ('local_address', 4551)

因此,即使客户端位于 NAT 之后,两个端口号也是相同的。这是怎么回事?我误解了 NAT 的工作原理吗?还是有其他命令可以获取客户端套接字绑定的物理地址?

如有任何见解,我们将不胜感激。

路由器可能正在使用端口地址转换(或 one-to-many NAT)。 wiki link 进一步引用

PAT attempts to preserve the original source port. If this source port is already used, PAT assigns the first available port number starting from the beginning of the appropriate port group 0-511, 512-1023, or 1024-65535. When there are no more ports available and there is more than one external IP address configured, PAT moves to the next IP address to try to allocate the original source port again. This process continues until it runs out of available ports and external IP addresses.

这应该是您在服务器上看到端口 4551 的原因。

(This link 应该也有助于弄清NAT和PAT的区别)