C++ 如何使TCP套接字与SO_BINDTODEVICE一起工作(针对路由表) 问题的背景:

C++ 如何使TCP套接字与SO_BINDTODEVICE一起工作(针对路由表) 问题的背景:,c++,c,sockets,tcp,network-programming,C++,C,Sockets,Tcp,Network Programming,在我们的机器上,我们有多个网络接口,这些接口通向不同的网络。可能存在重叠的IP地址(例如,两台不同网络中的两台不同机器具有相同的IP地址)。因此,当我们想与特定的对等方连接时,我们不仅需要指定它的IP地址,而且还需要指定我们的网络接口,从而连接到正确的网络。 我们希望用C/C++编写应用程序,能够通过TCP与特定的对等方连接 问题: 我正在尝试使用SO_BINDTODEVICE设置的套接字建立TCP连接。以下是一个简化的代码片段: sockfd = socket(AF_INET, SOCK_ST

在我们的机器上,我们有多个网络接口,这些接口通向不同的网络。可能存在重叠的IP地址(例如,两台不同网络中的两台不同机器具有相同的IP地址)。因此,当我们想与特定的对等方连接时,我们不仅需要指定它的IP地址,而且还需要指定我们的网络接口,从而连接到正确的网络。 我们希望用C/C++编写应用程序,能够通过TCP与特定的对等方连接

问题: 我正在尝试使用SO_BINDTODEVICE设置的套接字建立TCP连接。以下是一个简化的代码片段:

sockfd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, interface_name,
    strlen(interface_name));
connect(sockfd, (sockaddr *) &serv_addr, sizeof(serv_addr));
(我知道struct ifreq,但似乎只有它的第一个字段(ifr_name字段正在使用中),所以我只能传递接口的名称。)

  • 如果强制接口与路由表中的接口相同,则一切正常
  • 如果强制接口不同,则(使用Wireshark测试):
  • SYN从强制接口发送到所需的对等方
  • SYN,在强制接口上接收到来自所需对等方的ACK
  • ACK未从强制接口发送,且未建立连接。(然后转到步骤2。)
如何检查系统拒绝SYN、ACK或ACK的位置?以及如何正确地强制TCP套接字使用特定接口进行连接(针对路由表)

也许还有其他更方便的方法在所需的接口上创建TCP连接


谢谢

不要使用SO_BINDTODEVICE。并非所有平台都支持它,还有一种更简单的方法

而是将套接字绑定到正确网络上的本地IP地址,以用于连接到远程端

然后拨打connect


对于服务器端,除了指定一个端口而不是0,然后调用listen而不是connect之外,您也可以做同样的事情。

我知道这不是您的答案,但是您可以禁用其他接口,只启用您想要的网络,在您的情况下,您似乎需要所有接口,但我认为这种方法可以帮助其他人。您可以通过以下方式启用/禁用网络接口:

使能

ifr.ifr_flags = true; 
strcpy(ifr.ifr_name, "eth0"); //you could put any interface name beside "eth0" 
res = ioctl(sockfd, SIOCSIFFLAGS, &ifr);
对于disable,只需将flag设置为false,其余代码相同:

ifr.ifr_标志=真


这是内核配置的一个问题——在许多发行版上,在这种特定情况下,默认情况下,内核配置为拒绝传入的数据包

我在以下方面找到了解决此问题的方法:

要允许此类流量,您必须在计算机上设置一些变量(作为根):

其中
您的\u nic
是接收数据包的网络接口。注意更改
net.ipv4.conf.all.rp_过滤器
net.ipv4.conf.your_nic.rp_过滤器
,否则它将无法工作(内核默认为最严格的设置)


谢谢这将是一个很好的解决方案,但我忘了提到我们的机器在每个网络中都有相同的地址。对不起,我甚至不想说这个,因为我讨厌人们问你的问题而不是回答你的问题,但是为什么你在多个网络上有相同的IP?这听起来像是一个令人困惑的噩梦,很抱歉延迟。由于可扩展性,我们希望拥有许多相同的网络。具有许多接口的计算机是调度程序。在Windows上,bind()只影响传入的数据包。@JorgeFuentesGonzález,实际上这是不正确的。根据MSDN,“如果应用程序希望在具有多个网络接口和本地IP地址的本地计算机上选择特定的本地IP地址,请在发送之前使用绑定[…]
ifr.ifr_flags = true; 
strcpy(ifr.ifr_name, "eth0"); //you could put any interface name beside "eth0" 
res = ioctl(sockfd, SIOCSIFFLAGS, &ifr);
sysctl -w net.ipv4.conf.all.accept_local=1
sysctl -w net.ipv4.conf.all.rp_filter=0
sysctl -w net.ipv4.conf.your_nic.rp_filter=0