Python可以在打开套接字时select什么networking适配器?

运行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?? 

正常情况

  • 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都连接到不同的物理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') 

也可以看看:

  • Linux:如何强制使用特定的网络接口?
  • 如何制作一个传出套接字到一个特定的网络接口?

SO_BINDTODEVICE听起来很合理,但是通常你会通过绑定的IP地址间接选择一个设备。 更经常的是,你只需绑定到“”,绑定到机器的所有地址。