2009-11-19 17 views
7

Per quanto segue, sto assumendo una scheda di rete.Come ignorare i propri pacchetti udp di trasmissione

Ho un componente del mio programma che è progettato per consentire agli altri nella subnet di conoscerne l'esistenza. Per questo, ho implementato una soluzione in cui ogni volta che il programma si avvia (e periodicamente dopo) invia una trasmissione a INADDR_BROADCAST - chiunque ascolti sulla porta richiesta ricorderà da dove proviene per un uso successivo.

Il problema con questo è che non voglio ricordare le mie proprie trasmissioni. Pensavo che in teoria sarebbe stato facile farlo: basta trovare l'ip locale e confrontare quello che si ottiene in recvfrom.

Tuttavia, ho trovato difficile ottenere l'IP locale: getaddrinfo con NULL restituisce 127.0.0.1, getaddrinfo con il nome host restituisce l'ip pubblico. Qualcuno può indicarmi la direzione di trovare l'IP subnet attuale? Penso che mi manchi qualcosa di molto ovvio, ma mi manca ancora :)

Nota: ho letto altre domande SO su trasmissioni, in particolare questa: UDP-Broadcast on all interfaces ma non l'ho arrivato ancora al problema dell'interfaccia multipla.

+0

Perché non stai sfruttando soluzioni esistenti come mDNS (Multicast-DNS)? – jldupont

+0

mDNS è troppo complicato per le mie esigenze. – laura

risposta

7

Bene all'avvio è possibile trasmettere un messaggio diverso con valore casuale (ma tracciato), quindi attendere quel messaggio, per scoprire il proprio indirizzo, da quel momento in poi, è possibile inviare messaggi normali, ignorando i messaggi di provenienza.

+0

Questa è una buona idea, ma è un po 'hacker - le informazioni sono prontamente disponibili (ipconfig/ifconfig) quindi dovrei essere in grado di estrarlo in qualche modo – laura

+0

true, potresti cambiarlo per essere un parametro della tua applicazione, e poi fare un problema di scripting. Sono d'accordo è molto hacker –

+0

Accettare questo perché, anche se hacky, è l'unico modo per farlo senza chiamate API specifiche. Inoltre, sto già trasmettendo un valore tracciato, quindi ho solo bisogno di aggiungere una riga di codice in più. – laura

0

Ricerca per le opzioni scoket e vedere se queste opere: IP_MULTICAST_LOOP, IP_BLOCK_SOURCE

+1

Queste sono opzioni multicast. Niente a che vedere con la trasmissione. – EJP

1

getsockname (function documentation) possono scoprire l'indirizzo IP locale associato a un particolare socket. Se chiami questo sulla presa che stai usando per inviare la trasmissione, dovresti vedere lo stesso indirizzo IP che vedrai restituito da recvfrom.

+2

Restituisce '0.0.0.0' su Windows, alcuni strani gergo su linux. – laura

1

Su linux, è possibile ottenere l'indirizzo IP di una determinata interfaccia utilizzando ioctl con l'opzione SIOCGIFADDR. Non penso che funzioni per Windows, comunque. Per questo, dovrai fare qualcosa di sciocco come this.

0

(sto presumendo che si sta lavorando su Windows)

GetIpAddrTable fa esattamente questo! Restituisce dati su tutte le tue interfacce di rete, l'indirizzo IP è tra questi. C'è qualche trucco nell'ottenerli, ma non più che nel resto dei Winsock.

Ecco un esempio di 54 righe pronto a compilare che stampa tutte le interfacce di rete con le maschere IP e di rete e anche i filtri per il callback locale (127.0.0.1) poiché molto probabilmente non lo si desidera, ed è sempre lì, quindi non si può semplicemente ignorarlo:

(lavorato con msvc 19, Windows 10, Link contro Iphlpapi.lib e 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; 
} 

produrre questa uscita sulla mia macchina:

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 

L'unica cosa veramente strana è la prima chiamata a GetIpAddrTable, che fornisce solo la dimensione che è necessario allocare per il buffer. Penso che il resto del codice sia abbastanza esplicativo, altrimenti sono qui per domande. (Non ho 50 Rep, quindi non so se sarò in grado di rispondere alle domande, grazie StackOverflow!)

Problemi correlati