1

我有两个到 Internet 的网络链接,并且设置了两个默认路由:

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         gateway0        0.0.0.0         UG    0      0      eth0
default         gateway1        0.0.0.0         UG    0      0      eth1
...

我用 BINDTODEVICE 创建了两个套接字,这样我就可以将数据从 eth0 或 eth1 发送出去。我还尝试使用recvfrom(仅 UDP 数据)监听两个套接字,但我只能从路由中首先列出的任何接口成功读取数据。eth0例如,有效,但我从绑定到eth1.

在任一接口上运行 wireshark 都显示数据成功进入 - 也就是说,我可以看到数据从 Internet 发送到 Wireshark 中的 eth0 或 eth1 的 IP(因此 NAT 都不是问题),但我的程序只是阻塞recvfrom而没有得到任何数据。

我尝试bind在套接字上使用以使它们在各自接口的 IP 上侦听,并且还尝试不使用 bind 让它们在 0.0.0.0 上侦听(每个端口都在不同的端口上),但我仍然遇到同样的问题。

我怎样才能确保两个套接字都得到它们应该得到的数据?

编辑:示例代码:

int createDeviceBoundUDPSocket(uint32_t sip, uint16_t sport, const char* bind_dev) {
    printf("bind_dev = %s", bind_dev);
   int s = socket(AF_INET, SOCK_DGRAM, 0);   
   int result;
   struct sockaddr_in my_ip_addr;

   if (s < 0) {
      perror("socket");
      return s;
   }

   memset(&my_ip_addr, 0, sizeof(my_ip_addr));

   my_ip_addr.sin_family = AF_INET;
   my_ip_addr.sin_addr.s_addr = htonl(sip);
   my_ip_addr.sin_port = htons(sport);

   // commenting this section out doesn't seem to make a difference
   // listening on 0.0.0.0 or the interface's IP both have the same problem
   result = bind(s, (struct sockaddr*)(&my_ip_addr), sizeof(my_ip_addr));
   if (result < 0) {
      perror("Error in bind");
      return result;
   }

   if (bind_dev) {
      // Bind to specific device.
      if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE,
                     bind_dev, strlen(bind_dev) + 1)) {
         perror("Error binding to device");
         return -1;
      }
   }

   return s;
}
4

1 回答 1

0

正如Linux 高级路由和流量控制指南所暗示的,解决方案是关闭反向路径过滤。不确定三个接口中的哪一个需要关闭它,但是做

echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter

让它工作。

于 2014-01-24T00:22:18.880 回答