使用INADDR_ANY更改udp服务器绑定的默认源IP

时间:2012-04-02 11:05:13

标签: linux sockets udp ip

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

但是,在从服务器发送回复时,默认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?这是对应用程序代码的更多控制,以决定源地址。同样有意义的是,回复中的源地址与查询所在的目标地址相同。

2 个答案:

答案 0 :(得分: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。

  3. 此外,您只需使用bind()来关联传出数据包的源IP。

答案 1 :(得分:0)

将套接字绑定到一个地址后,您将无法再将其绑定到另一个地址,否则将收到错误EINVAL。但是本文Setting the source IP for a UDP socket

中描述了另一种技术