Python 在打开套接字时可以选择哪个网络适配器吗?
- 2024-10-30 08:36:00
- admin 原创
- 47
问题描述:
运行 Python 应用程序的目标计算机将拥有三个可用的网络接口。一般来说,这三个网络会有很大差异,但其中两个网络可能位于相似的网络上。
在下面的例子中,我无法控制 ETH 2 上的目标地址(因为它是一个预配置的系统),所以我强制选择以编程方式使用哪个适配器。
我相当肯定这将取决于操作系统如何路由连接。我希望有一种独立于平台的方法来使用 Python 解决这个问题,因为这个应用程序可能需要在 Windows 7 和 Linux 机器上运行。
示例代码
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.0.2', 8000)) # Which device will this connect to??
正常情况
ETH 0 来源:192.168.0.1
ETH 0 目的地:192.168.0.2
ETH 1 来源:10.20.30.1
ETH 1 目的地:10.20.30.2
ETH 2 来源:60.50.40.1
ETH 2 目的地:60.50.40.1
可能出现的麻烦案例
ETH 0 来源:192.168.0.1
ETH 0 目的地:192.168.0.2
ETH 1 来源:10.20.30.1
ETH 1 目的地:10.20.30.2
ETH 2 来源:192.168.0.3
ETH 2 目的地:192.168.0.2
附加信息
适配器 ETH0、1 和 2 都连接到不同的物理网络
解决方案 1:
我对 Windows 不太了解,但在 Linux 上,通常在做出路由决策之前不会选择接口,因此您通常无法决定数据包离开哪个接口。
不过,在 Linux 上,你确实可以选择使用SO_BINDTODEVICE
(参见man 7 socket
)。这会将套接字绑定到设备,但只有 root 才能在套接字上设置此选项。
刚刚检查过,python 套接字库尚未SO_BINDTODEVICE
定义,但您可以从中获取它socket.h
:
# from socket.h
# define SO_BINDTODEVICE 25
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, 25, 'eth0')
参见:
Linux:如何强制使用特定的网络接口?
如何创建到特定网络接口的传出套接字?
解决方案 2:
在 Windows 上,如果您知道要使用的接口的 IP 地址,则只需在连接之前绑定到该地址即可。在 Linux 上,使用套接字选项 SO_BINDTODEVICE(如 JimB 所建议的那样)(似乎也是特权调用)。
即在 Windows 上
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('192.168.0.1', 0))
s.connect(('...'))
在 Windows 下绑定源地址,选择与该设备具有相同 IP 地址的接口,即使该 IP 地址具有更高的路由度量成本。但这在 Linux 下不起作用,因为它总是用所选设备的 IP 地址覆盖源地址。路由完全基于目标地址完成。唯一的例外似乎是如果您将源地址设置为 127.0.0.1,则 Linux 会阻止这些数据包离开该框。
解决方案 3:
SO_BINDTODEVICE 听起来很合理,但通常你会通过绑定到的 IP 地址间接选择设备。更常见的情况是,你只需绑定到 '',即可绑定到机器的所有地址。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件