【问题标题】:How to stop behaviour: C++ Socket sendto changes interface如何停止行为:C++ Socket sendto 更改接口
【发布时间】:2013-10-21 13:07:17
【问题描述】:

我运行 Ubuntu 12.04,我目前正在编写 C++ 代码来创建一个 UDP 套接字,它使用 sendto 将数据包发送到各个目的地。现在碰巧我的笔记本电脑同时具有 wlan0eth0 接口。如果我将它绑定到其中任何一个,使用 IP 地址和 SO_BINDTODEVICE 选项,根据目标地址,sendto 仍会决定使用适合他的另一个接口。

具体来说,如果我将一个 UDP 套接字绑定到 eth0 接口,带有它的 ip 地址和一些端口,然后我将一个数据包发送到另一台笔记本电脑(本地,只有 wifi 访问),它将决定使用我的 wlan0 接口。

我知道这种行为有其优点,但我希望能够将其关闭,即我希望能够对套接字说它应该只使用我分配给它的一个接口。

建议?

编辑:

struct sockaddr_storage sa = address;
fd = socket(address.get_family(), SOCK_DGRAM, 0);
char *devname = "wlan0";
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, devname, strlen(devname));
bind(fd, (sockaddr*)&sa, len);

【问题讨论】:

  • “如果我将它绑定到其中任何一个,使用 IP 地址和 SO_BINDTODEVICE 选项”我一直认为 SO_BINDTODEVICE 获得了一个接口名称(至少这就是我将它用于多播的方式,并且它工作正常)
  • 您使用bind() 和接口的地址,这不起作用? (我假设他们有不同的地址)
  • @Hasturkun:他们有不同的地址

标签: c++ sockets


【解决方案1】:

使用 SO_BINDTODEVICE 或 bind 将套接字绑定到接口定义接收数据包的过滤器。当没有使用指定接口接收到数据包时,它不会传递到套接字的接收队列。见:http://linux.die.net/man/7/socket

但是将套接字绑定到接口不会影响正常的 IP 路由过程。当您发送数据包时,网络 IP 堆栈有责任找到最佳路由并通过硬件适配器发送 IP 数据包。这可以是以太网适配器,但它不是具有和绑定操作的控制器。

当您想在特定接口发送数据包时,您需要原始套接字。您构建完整的数据包内容,包括 IP 和硬件层(可能是以太网)并使用原始套接字发送它。

【讨论】:

  • 如果我动态更改路由表会怎样?
  • 您可以更改路由表。这将控制数据包的传输方式。如果您的路由器的 WLAN 端口有一个 IP 地址,而电缆端口有一个不同的 IP 地址,则您可以控制路由。但要小心,因为这会影响来自所有进程的数据包的路由。
  • 使用高级路由,您可以给 UDP 数据包一个 MARK,将它们定向到您选择的表,您可以在那里设置选择的默认网关。这不会影响未标记的数据包。有趣的是,我认为 SO_BINDTODEVICE 确实会强制您使用指定的接口。只是主路由表有一个默认网关(我假设通常将其设置为 eth0 网关)。因此,如果您不提供正确的路由,绑定到 wlan0 对您没有任何好处。您可以通过传入的 ICMP 消息 HOST UNREACHABLE 注意到这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-05
  • 2018-10-11
  • 1970-01-01
  • 2016-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多