2009-11-19 99 views
7

对于以下我假设一个网卡。如何忽略自己的广播udp数据包

我有我的程序的一个组件,旨在让子网中的其他人知道它的存在。为此,我实施了一个解决方案,无论程序什么时候启动(并定期在后面),它都会发送一个广播到INADDR_BROADCAST - 监听所需端口的人将会记住它来自哪里以供以后使用。

问题在于我不想记住自己的广播。我认为理论上这很容易做到 - 只需找出本地IP并比较你在recvfrom中得到的结果。

但是,我发现很难得到本地IP:getaddrinfo与NULL返回127.0.0.1,getaddrinfo与主机名返回公共IP。任何人都可以指向我的方向找到实际的子网IP?我想我一定在这里错过了一些非常明显的东西,但是...我仍然想念它:)

注意:我已经阅读过有关广播的其他SO问题,特别是这一个:UDP-Broadcast on all interfaces但我没有还没有得到多个界面问题。

+0

为什么不利用现有的解决方案,如mDNS(Multicast-DNS)? – jldupont 2009-11-19 13:27:55

+0

mDNS对我的需求来说太复杂了。 – laura 2009-11-19 14:02:11

回答

7

在启动时,您可以随机播放不同的消息(但是是跟踪的),然后等待该消息,发现自己的地址,然后发送正常消息,忽略源消息。

+0

这是一个不错的主意,但它有点骇人听闻 - 信息是随时可用的(ipconfig/ifconfig),所以我应该能够以某种方式提取它 – laura 2009-11-19 09:56:38

+0

是真的,你可以改变它作为你的应用程序的参数,然后使一个脚本问题。我同意这是非常hackish – 2009-11-19 09:59:42

+0

接受这一点,因为虽然hacky,没有特定的API调用是唯一的方法。另外,我已经发送了一个跟踪值,所以我只需要添加一行额外的代码。 – laura 2009-11-19 16:31:06

0

搜索SCOKET选项,看看是否这些作品: IP_MULTICAST_LOOP,IP_BLOCK_SOURCE

+1

这些是多播选项。与广播无关。 – EJP 2010-12-07 02:05:08

1

getsocknamefunction documentation)可以发现与特定套接字关联的本地IP地址。如果您在用于发送广播的套接字上调用此选项,则应该看到与recvfrom返回的IP地址相同的IP地址。

+2

在Windows上返回'0.0.0.0',在linux上出现一些奇怪的乱码。 – laura 2009-11-19 16:31:41

1

在linux上,您可以使用ioctl和SIOCGIFADDR选项来获取给定接口的IP地址。不过,我认为这不适用于Windows。为此,你必须做一些愚蠢的事情,比如this

0

(我假设你使用的是Windows)

GetIpAddrTable正是这么做的!它会返回有关所有网络接口的数据,其中的IP地址就在其中。获得它们有一些技巧,但不会超过Winsocks的其余部分。

这是一个可以编辑54行的例子,它可以打印所有的IP和网络掩码的网络接口,也可以过滤本地回调(127.0.0.1),因为你很可能不想这样做,而且总是存在的,所以你不能忽略它:

#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; 
} 

生产我的机器上这个输出(用MSVC 19,窗口10,链接对Iphlpapi.lib和WS2_32.LIB工作):

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,它只是给你需要分配给缓冲区的大小。我认为其余的代码是非常明显的,如果不是我在这里的问题。 (我没有hav 50 Rep,所以我不知道我是否能够回答问题,谢谢Stackoverflow!)