当我从绑定到INADDR_ANY的UDP套接字发送数据包时,如何找出操作系统选择使用的IP地址?
int s = socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in src;
src.sin_family = AF_INET;
src.sin_port = 12345;
src.sin_addr.s_addr = INADDR_ANY;
bind(s, (struct sockaddr*)&src, sizeof(src));
char msg[] = "Hello";
sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_port = 12345;
dest.sin_addr.s_addr = (in_addr_t)0xdeadbeef;
sendto(s, msg, sizeof(msg), 0, (struct sockaddr*)&dest, sizeof(dest));
使用什么源地址发送数据包?理想情况下会有sendtofrom()
函数,如recvfrom()
,它返回内核选择的地址。
在我的应用程序中,我绑定到INADDR_ANY并将数据包发送到STUN服务器(我不想使用路由表来选择源地址:内核的选择是精细)。但是,为了做ICE,我需要获得"基地址" "服务器反身地址",即。我需要知道使用哪个本地地址发送STUN请求。我会接受Windows或POSIX特定的答案,建议从路由表中查找地址。
答案 0 :(得分:1)
不幸的是,无法查询使用的是哪个源IP地址。例如,在Windows上,您必须编写一个低级NDIS驱动程序才能获取该信息。但是,如果您使用WSASendMsg()
/ sendmsg()
而不是sendto()
,则可以传入in_pktinfo
结构以指定要用于传出数据包的源IP地址。
答案 1 :(得分:0)
我最近遇到了同样的问题。
我要解决这个问题的方法是
示例:
struct ifreq ifr;
...
recvmsg(fd, &msg...)
...
//
if (msg.msg_controllen >= sizeof(struct cmsghdr))
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
{
iface_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
}
if_indextoname(iface_index , ifr.ifr_name);
mret=setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr));
sendmsg(...);
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "");
mret=setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr));