Linux Python在打开套接字时可以选择什么网络适配器吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8437726/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can Python select what network adapter when opening a socket?
提问by Adam Lewis
The target machine running the python application will have three network interfaces available to it. In general all three networks will be vastly different, however there is a possibility that two of the three could be on similar networks.
运行 python 应用程序的目标机器将有三个可用的网络接口。一般来说,所有三个网络都会有很大的不同,但是三个网络中的两个可能在类似的网络上。
In the example below I do not have control over the destination address on ETH 2 (as it a pre-configured system), so I forced into selecting what adapter to use programmaticly.
在下面的示例中,我无法控制 ETH 2 上的目标地址(因为它是一个预配置的系统),因此我被迫以编程方式选择要使用的适配器。
I am fairly sure that this will fall on how the OS works with routing the connections. My hope is that there will be a platform independent way to solve the issue using python, because there is a possibility that this application will need to run on Windows 7 as well as a Linux machine.
我相当确定这将取决于操作系统如何处理连接路由。我希望有一种独立于平台的方法来使用 python 解决这个问题,因为这个应用程序可能需要在 Windows 7 和 Linux 机器上运行。
Example Code
示例代码
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.0.2', 8000)) # Which device will this connect to??
Normal Case
正常情况
- ETH 0 Source: 192.168.0.1
- ETH 0 Destination: 192.168.0.2
- ETH 1 Source: 10.20.30.1
- ETH 1 Destination: 10.20.30.2
- ETH 2 Source: 60.50.40.1
- ETH 2 Destination: 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 来源:60.50.40.1
- ETH 2 目的地:60.50.40.1
Possible Trouble Case
可能的故障案例
- ETH 0 Source: 192.168.0.1
- ETH 0 Destination: 192.168.0.2
- ETH 1 Source: 10.20.30.1
- ETH 1 Destination: 10.20.30.2
- ETH 2 Source: 192.168.0.3
- ETH 2 Destination: 192.168.0.2
- 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
Additional Information
Adapters ETH0,1,and 2 are all connected to different physical netoworks
附加信息
适配器 ETH0、1 和 2 都连接到不同的物理网络
采纳答案by Lloyd Macrohon
On Windows, if you know the IP address of the interface you want to use, just bind to that before you connect. On Linux,use socket option SO_BINDTODEVICE as suggested by JimB (seems to be a privileged call too).
在 Windows 上,如果您知道要使用的接口的 IP 地址,只需在连接之前绑定到该地址即可。在 Linux 上,按照 JimB 的建议使用套接字选项 SO_BINDTODEVICE(似乎也是一个特权调用)。
i.e. on Windows
即在 Windows 上
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('192.168.0.1', 0))
s.connect(('...'))
Binding source address under Windows, selects the interface with the same IP address as that device, even if that IP address has a higher routing metric cost. This doesn't work under Linux though, as it always overwrites the source address with the IP address of the selected device. Routing is done based solely on the destination address. The only exception it seems is if you set source address to 127.0.0.1, then Linux prevents these packets from going out of that box.
Windows 下绑定源地址,选择与该设备 IP 地址相同的接口,即使该 IP 地址具有更高的路由度量成本。但是这在 Linux 下不起作用,因为它总是用所选设备的 IP 地址覆盖源地址。路由是完全基于目标地址完成的。唯一的例外似乎是,如果您将源地址设置为 127.0.0.1,则 Linux 会阻止这些数据包从该框外出去。
回答by JimB
I can't speak much for Windows, but on Linux the interface is normally not chosen until a routing decision is made, therefore you usually don't have a say on which interface your packets leave.
对于 Windows,我不能说太多,但在 Linux 上,通常在做出路由决定之前不会选择接口,因此您通常对数据包离开哪个接口没有发言权。
You do have the option though, of using SO_BINDTODEVICE
(see man 7 socket
) on Linux. This binds a socket to a device, however, only root can set this option on a socket.
不过,您确实可以选择在 Linux上使用SO_BINDTODEVICE
(请参阅 参考资料man 7 socket
)。这会将套接字绑定到设备,但是,只有 root 可以在套接字上设置此选项。
Just checked, and the python socket library doesn't have SO_BINDTODEVICE
defined, but you get it from socket.h
:
刚刚检查过,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')
See also:
也可以看看:
回答by dstromberg
SO_BINDTODEVICE sounds reasonable, but normally you'll indirectly select a device by what IP address you bind to. More often than that, you'll just bind to '', to bind to all address of the machine.
SO_BINDTODEVICE 听起来很合理,但通常您会通过绑定的 IP 地址间接选择设备。更常见的是,您只需绑定到 '',即可绑定到机器的所有地址。