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