运行python应用程序的目标机器将有三个可用的networking接口。 总的来说,这三个networking将会有很大的不同,然而有可能三个networking中的两个可能在类似的networking上。
在下面的例子中,我不能控制ETH 2上的目标地址(因为它是一个预先configuration好的系统),所以我不得不以编程方式select使用哪个适配器。
我相当肯定,这将取决于操作系统如何使用路由连接。 我的希望是将有一个平台独立的方式来解决这个问题使用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都连接到不同的物理networking
在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会阻止这些数据包从该框中移出。
我不能为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')
也可以看看:
SO_BINDTODEVICE听起来很合理,但是通常你会通过绑定的IP地址间接选择一个设备。 更经常的是,你只需绑定到“”,绑定到机器的所有地址。