在绑定到0.0.0.0时如何查找源IP地址

4 投票
2 回答
4353 浏览
提问于 2025-04-18 01:19

当我把一个UDP套接字绑定到 ("", 1234)("0.0.0.0", 1234) 时,能不能知道它实际会用哪个IP地址发送数据呢?

在下面的代码中,getsockname 只告诉我我绑定了什么。但是当我发送一个数据包时,我发现我的IP地址是 10.0.0.2

我是不是得自己去查看我的网络接口,推测出这个地址?如果是这样也没问题,但有没有什么可靠的方法来做到这一点呢?

from socket import *
s = socket(AF_INET, SOCK_DGRAM)
s.bind(("", 1234))
print(s.getsockname()) # prints ("0.0.0.0", 1234)
s.sendto("hello", ("10.0.0.3", 1234)) # sends from 10.0.0.2

我试过这样做

import socket
print(socket.gethostbyname(socket.gethostname()))

但这似乎不太可靠(在我期待 10.0.0.2 的情况下,我得到了 127.0.1.1)。

我明白了,绑定到 0.0.0.0 意味着我绑定到了所有本地网络接口。这是否意味着我发送数据时,源IP地址会由路由表决定?如果是这样,我还能从Python中以可靠的方式获取这个地址吗?

2 个回答

1

这其实是一个通常情况下你不需要知道的答案。可能和你的情况不太相关。

你可以看看 socket.gethostbyname_ex(socket.gethostname())。这个命令会显示所有可能的IP地址和主机名。因为你没有绑定到某个特定的IP地址,所以你可以从这些地址中接收数据。它们就是你的源IP地址。

你并不需要知道你发送数据时的确切地址。如果数据经过NAT(网络地址转换)、进入互联网或者通过VPN,接收方可能会看到另一个地址。接收方会知道数据包是从哪里来的,并可以发送回复。

@Joachim_Pileborg 说得也对。通常情况下,这种做法并不常见。

如果你需要指定某个网络接口,就绑定到它。如果不需要,那你可能根本不需要这样做。

2

当你发送数据包时,使用的IP地址是由路由表决定的。路由表就像一个地图,告诉数据包该走哪条路。不同的平台可能有不同的方法来查询这个路由表,但有一种比较通用的方法就是先连接这个套接字。

你也可以使用另一个套接字来专门查询这些信息。例如:

from socket import *
s = socket(AF_INET, SOCK_DGRAM)
s.bind(("", 1234))
print(s.getsockname()) # prints ("0.0.0.0", 1234)
sq = socket(AF_INET, SOCK_DGRAM)
sq.connect(("10.0.0.3", 1234))
print(sq.getsockname()[0])
sq.close()
s.sendto("hello", ("10.0.0.3", 1234)) # sends from 10.0.0.2

撰写回答