2009-11-19 96 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!)