我的应用程序打开了一个绑定到INADDR_ANY的UDP套接字来监听我服务器上所有接口上的数据包。 我通过相同的套接字发送回复。
但是,在从服务器发送回复时,默认IP由Linux的IP层根据select哪个接口进行分组来select。 与此接口关联的IP可能不是该UDP服务器从客户端获取查询的目的地址。 因此,来自服务器的回复的来源IP与查询来自的目的地IP不同。 客户可能会对这样的回复感到不舒服。
以下链接给出了使用UDP的INADDR_ANY的行为: http : //www.cs.cmu.edu/~srini/15-441/F01.full/www/assignments/P2/htmlsim_split/node18.html
我怎样才能改变这个默认行为,并在源地址中使用特定的接口IP? 这是更多的控制应用程序代码来决定什么将是源地址。 同样有意义的是,回复中的源地址与查询出现的目的地址相同。
假设你有多个接口(其中一个具有正确的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地址。 唯一的缺点是,你停止在这个套接字的任何其他接口上接收消息。
可能的解决方法是:
使用一个单独的套接字进行监听,而不是绑定到任何接口,另一个发送绑定到你需要的接口。
在发送消息之前绑定到接口并绑定到“”,并在发送之后立即清除以前的绑定。 然而,你可能会丢失在这个时间帧内接收到的任何数据包,你的套接字绑定接口eth0,数据包到达eth1。
你也可以简单地使用bind()来关联一个输出数据包的源ip。