【问题标题】:changing default source IP for udp server bind with INADDR_ANY更改与 INADDR_ANY 绑定的 udp 服务器的默认源 IP
【发布时间】:2012-04-16 01:03:08
【问题描述】:

我的应用程序打开了一个绑定到 INADDR_ANY 的 UDP 套接字,以侦听服务器所有接口上的数据包。我正在通过同一个套接字发送回复。

但是,当从服务器发送回复时,默认 IP 由 linux 的 IP 层选择,具体取决于为数据包选择的接口。与此接口关联的 IP 可能不是此 UDP 服务器从客户端获取查询的目标地址。因此,来自服务器的回复的源 IP 与查询所用的目标 IP 不同。客户可能会对这样的回复感到不自在。

以下链接给出了 INADDR_ANY 与 UDP 的行为: http://www.cs.cmu.edu/~srini/15-441/F01.full/www/assignments/P2/htmlsim_split/node18.html

如何更改此默认行为并在源地址中使用特定的接口 IP?这是对应用程序代码的更多控制,以决定什么是源地址。回复中的源地址与查询所用的目标地址相同也是有意义的。

【问题讨论】:

  • 会多做一些工作,但是您没有考虑过使用原始套接字代替吗?然后您可以随意更改 IP 和 UDP 标头中的所有字段。
  • @JoachimPileborg 我不建议为此使用原始套接字。您基本上必须在您的应用程序中重新实现 UDP,在内核不知情的情况下选择要使用的 UDP 端口(并且可能会干扰它自己的选择),并且您需要 root 访问权限。
  • 对于 UDP 选择哪个接口作为它的服务器源地址,我没有办法发言吗?
  • @superbCoder 当然有,除非我误解了您的某些要求。看看下面我的回答
  • 如果自动选择的接口不是发送者发送到的那个接口,你一定有一个非常奇怪的路由表。

标签: linux sockets udp ip


【解决方案1】:

当然,假设您有多个接口(其中一个具有正确的 ip)您可以绑定到一个接口以进行传出响应。 看看 SO_BINDTODEVICE 套接字选项。

int bind_sock2inf(int sock, char *interface_name)
{
    int status = -1;
    struct ifreq ifr;

    memset(&ifr, 0, sizeof(ifr));
    snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), interface_name);
    if ( (status = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
                (void *)&ifr, sizeof(ifr))) < 0) {
        log_debug(4, "Failed binding to interface named %s", inf_name);
    }
    else log_debug(3, "Binding to interface %s", inf_name);

    return status;
}

现在您的传出请求应该会自动使用附加到此接口的 IP 地址。唯一的缺点是您停止在此套接字的任何其他接口上接收消息。

可能的解决方法是:

  1. 使用单独的套接字进行侦听,该套接字未绑定到任何接口,另一个用于发送,并在发送前绑定到您需要的任何接口。

  2. 在发送消息之前绑定到接口并再次绑定到“”,这会在发送后立即清除之前的绑定。但是,您可能会丢失在此时间范围内收到的任何数据包,您的套接字绑定到接口,例如 eth0 并且数据包到达 eth1。

您也可以简单地使用bind() 为传出数据包关联源IP。

【讨论】:

    【解决方案2】:

    一旦套接字绑定到一个地址,你就不能再将它绑定到另一个地址,否则你会得到错误EINVAL。但是这篇文章中描述了另一种技术Setting the source IP for a UDP socket

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-28
      • 1970-01-01
      • 2021-01-20
      • 2019-11-19
      • 1970-01-01
      • 2016-09-19
      • 2023-04-07
      • 1970-01-01
      相关资源
      最近更新 更多