如何忽略自己的广播udp数据包

对于以下我假设一张网卡。

我有一个程序的组件,旨在让子网中的其他人知道它的存在。 为此,我实现了一个解决方案,无论何时程序启动(以及之后定期)它都会向INADDR_BROADCAST发送广播 – 无论谁收听所需的端口,都会记住它来自哪里供以后使用。

这个问题是我不想记住我自己的广播。 我认为理论上这很容易做 – 只需找出本地ip并与recvfrom内容进行比较。

但是,我发现很难获得本地IP:带有NULL的getaddrinfo返回127.0.0.1 ,带有主机名的getaddrinfo返回公共IP。 任何人都可以指向我找到实际的子网IP的方向? 我想我必须错过一些非常明显的东西但是……我还是错过了:)

注意:我已经阅读了有关广播的其他SO问题,特别是这一个: 所有接口上的UDP-Broadcast,但我尚未解决多接口问题。

在启动时,您可以使用随机(但跟踪)值广播不同的消息,然后等待该消息,发现您自己的地址,从那时起,您可以发送正常消息,忽略您的来源消息。

getsockname ( 函数文档 )可以发现与特定套接字关联的本地IP地址。 如果你在用于发送广播的套接字上调用它,你应该会看到recvfrom返回的相同IP地址。

在linux上,您可以使用带有SIOCGIFADDR选项的ioctl获取给定接口的IP地址。 不过,我认为这不适用于Windows。 为此,你必须像这样做一些傻瓜。

(我假设您正在使用Windows)

GetIpAddrTable正是这样做的! 它返回有关所有网络接口的数据,其中包含IP地址。 获得它们有一些技巧,但不会超过其他的Winsocks。

这是一个准备编译的54行示例,它使用IP和网络掩码打印所有网络接口,并且还为本地回调(127.0.0.1)过滤,因为您很可能不希望这样,并且它始终存在,所以你不能忽视它:

(使用msvc 19,windows 10,链接Iphlpapi.lib和Ws2_32.lib)

 #include "stdio.h" #include "Winsock2.h" #include "Iphlpapi.h" int main(){ int error; ULONG size = 0; MIB_IPADDRTABLE* meta_table = nullptr; error = GetIpAddrTable(meta_table, &size, false); if(error != ERROR_INSUFFICIENT_BUFFER) return -1; meta_table = (MIB_IPADDRTABLE*)malloc(size); error = GetIpAddrTable(meta_table, &size, false); if(error != NO_ERROR) return -1; int os_interface_count = meta_table->dwNumEntries; for(int i = 0; i < os_interface_count; i++){ printf("interface:\n"); { in_addr mask; in_addr address; address.S_un.S_addr = meta_table->table[i].dwAddr; mask.S_un.S_addr = meta_table->table[i].dwMask; printf("index: %d\n", meta_table->table[i].dwIndex); printf("address: %s\n", inet_ntoa(address)); printf("mask: %s\n", inet_ntoa(mask)); } { in_addr callback_address; callback_address.S_un.S_un_b.s_b1 = 127; callback_address.S_un.S_un_b.s_b2 = 0; callback_address.S_un.S_un_b.s_b3 = 0; callback_address.S_un.S_un_b.s_b4 = 1; if(meta_table->table[i].dwAddr == callback_address.S_un.S_addr) printf("local callback!\n"); } } free(meta_table); return 0; } 

在我的机器上产生这个输出:

 interface: index: 7 address: 192.168.56.1 mask: 255.255.255.0 interface: index: 1 address: 127.0.0.1 mask: 255.0.0.0 local callback! interface: index: 11 address: 192.168.178.181 mask: 255.255.255.0 

唯一真正奇怪的是第一次调用GetIpAddrTable ,它只是为你提供了为缓冲区分配的大小。 我认为剩下的代码是非常自我解释的,如果不是我在这里提问。 (我没有50个Rep,所以我不知道我是否能够回答问题,谢谢Stackoverflow!)

搜索scoket选项并查看它们是否有效:IP_MULTICAST_LOOP,IP_BLOCK_SOURCE