我在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网络的公共地址(我期望),根据我对NAT的理解,某些端口号应与实际端口号不同由客户使用,用于地址转换。
但是,如果我在客户端上使用了getsockname()函数,我将得到与服务器给出的端口号相同的端口号。
返回代码中的示例。
在服务器上:
client_socket.getpeername()
>>> ('WiFi_address', 4551)
在客户端:
sock.getsockname()
>>> ('local_address', 4551)
因此,即使客户端位于NAT后面,两个端口号都是相同的。情况怎么样?我误解了NAT是如何工作的吗?或者是否有另一个命令来获取客户端套接字绑定的物理地址?
任何见解都将受到赞赏。
答案 0 :(得分:1)
路由器可能正在使用端口地址转换(或one-to-many NAT)。维基链接进一步引用
PAT尝试保留原始源端口。如果这个源端口 已经使用,PAT分配第一个可用的端口号 从适当的端口组0-511,512-1023开始,或 1024-65535。当没有更多端口可用时,还有更多端口 如果配置了一个外部IP地址,PAT将移至下一个IP 尝试再次分配原始源端口的地址。这个 进程一直持续到可用端口和外部IP耗尽为止 地址。
这应该是您在服务器上看到端口4551的原因。
(This link也应该有助于澄清NAT和PAT之间的区别)