运行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??
正常情况
可能出现的问题
其他信息
适配器ETH0,1和2都连接到不同的物理网络
答案 0 :(得分:19)
对于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')
另见:
答案 1 :(得分:14)
在Windows上,如果您知道要使用的接口的IP地址,请在连接之前绑定到该地址。在Linux上,使用JimB建议的套接字选项SO_BINDTODEVICE(似乎也是特权电话)。
即。在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会阻止这些数据包离开该框。
答案 2 :(得分:-1)
SO_BINDTODEVICE听起来合理,但通常您会通过绑定的IP地址间接选择设备。更常见的是,您只需绑定到'',即可绑定到机器的所有地址。