Linux - 打开特定网络适配器的套接字
Linux - Open socket for specific network adapter
问题
我有一台计算机应该通过 TCP 连接到两台机器(或者更确切地说是一组单独的设备)。让事情变得棘手的是,这两台机器共享相同的 IP 地址范围并且也有部分相同的地址,只有一台通过一个以太网适配器连接,另一台通过第二个以太网适配器连接。
注意:地址范围不是我定义的,而是由这些机器的制造商定义的。不幸的是,我不得不和他们一起生活。
应该执行该工作的程序是用 C/C++ 编写的。从程序的角度来看,连接是传出的,所以我不能只绑定传入连接并保留它们的 ID。
可能的解决方案
经过一些研究(例如这里:Problems with SO_BINDTODEVICE Linux socket option),我尝试使用
将套接字绑定到设备
setsockopt(socket, SOL_SOCKET, SO_BINDTODEVICE, "adapter name", strlen("adapter name");
事实证明,这只有在程序 运行 具有超级用户权限的情况下才有效,我会尽量避免这种情况。否则,函数 returns 一个错误代码,转换为 permission denied(我忘记了确切的短语)。
其他解决方案?
有没有其他方法,我怎么能做到这一点?
仅仅将套接字固定到一个特定的接口是行不通的,因为还有很多事情要做...如果你连接到 192.168.0.3,内核会查看路由 table 找到正确的接口来发送数据包。如果要使用 IP 通信,则路由 table 中不能有两个具有相同子网规范 (192.168.0.0/24) 的条目。我想到了两个解决方案:
为适配器设置预路由 NAT 以映射地址。例如,您可以将 eth0
收到的包中的所有源地址映射到 192.168.0.0
范围,并将 eth1
收到的所有源地址映射到 192.168.1.0
。如果在预路由过滤器链中添加此地址转换,内核甚至不会注意到子网在内部使用相同的 IP 地址范围。
如果没有重复的 ip 地址(例如两个网络中的 192.168.0.2),您可以设置一个 bridge
接口。网桥的行为就像一个接口,连接到两个网络。网桥的行为就像一个软件交换机。对于内核(以及您的程序)来说,它看起来好像只有一个适配器,所有设备都插入其中。
这两种解决方案都需要超级用户权限才能设置,但设置一次后,您的程序就不需要它们了。
问题
我有一台计算机应该通过 TCP 连接到两台机器(或者更确切地说是一组单独的设备)。让事情变得棘手的是,这两台机器共享相同的 IP 地址范围并且也有部分相同的地址,只有一台通过一个以太网适配器连接,另一台通过第二个以太网适配器连接。
注意:地址范围不是我定义的,而是由这些机器的制造商定义的。不幸的是,我不得不和他们一起生活。
应该执行该工作的程序是用 C/C++ 编写的。从程序的角度来看,连接是传出的,所以我不能只绑定传入连接并保留它们的 ID。
可能的解决方案
经过一些研究(例如这里:Problems with SO_BINDTODEVICE Linux socket option),我尝试使用
将套接字绑定到设备setsockopt(socket, SOL_SOCKET, SO_BINDTODEVICE, "adapter name", strlen("adapter name");
事实证明,这只有在程序 运行 具有超级用户权限的情况下才有效,我会尽量避免这种情况。否则,函数 returns 一个错误代码,转换为 permission denied(我忘记了确切的短语)。
其他解决方案?
有没有其他方法,我怎么能做到这一点?
仅仅将套接字固定到一个特定的接口是行不通的,因为还有很多事情要做...如果你连接到 192.168.0.3,内核会查看路由 table 找到正确的接口来发送数据包。如果要使用 IP 通信,则路由 table 中不能有两个具有相同子网规范 (192.168.0.0/24) 的条目。我想到了两个解决方案:
为适配器设置预路由 NAT 以映射地址。例如,您可以将
eth0
收到的包中的所有源地址映射到192.168.0.0
范围,并将eth1
收到的所有源地址映射到192.168.1.0
。如果在预路由过滤器链中添加此地址转换,内核甚至不会注意到子网在内部使用相同的 IP 地址范围。如果没有重复的 ip 地址(例如两个网络中的 192.168.0.2),您可以设置一个
bridge
接口。网桥的行为就像一个接口,连接到两个网络。网桥的行为就像一个软件交换机。对于内核(以及您的程序)来说,它看起来好像只有一个适配器,所有设备都插入其中。
这两种解决方案都需要超级用户权限才能设置,但设置一次后,您的程序就不需要它们了。