2012-04-02 149 views
2

我的应用程序已打开绑定到INADDR_ANY的UDP套接字来侦听服务器上所有接口上的数据包。我通过相同的套接字发送回复。更改udp服务器与INADDR_ANY绑定的默认源IP

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

+0

这将是一个更多的工作,但你没有想过使用原始套接字呢?然后,您可以随意更改IP和UDP标头中的所有字段。 – 2012-04-02 11:14:28

+0

@JoachimPileborg我不会推荐使用原始套接字。您将不得不在应用程序中重新实现UDP,在没有内核知识的情况下选择使用UDP端口(并可能干扰其自己的选择),并且您需要root访问权限。 – Celada 2012-04-02 14:28:34

+0

有没有办法让我可以说,UDP选择哪个接口作为服务器源地址? – superbCoder 2012-04-03 05:27:40

回答

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。