Как игнорировать ваши собственные широковещательные пакеты udp - PullRequest
8 голосов
/ 19 ноября 2009

Для следующего я предполагаю одну сетевую карту.

У меня есть компонент моей программы, который предназначен для того, чтобы другие участники подсети знали о его существовании. Для этого я реализовал решение, при котором всякий раз, когда программа запускается (и периодически после этого), она отправляет широковещательную рассылку INADDR_BROADCAST - тот, кто прослушивает требуемый порт, запоминает, откуда она пришла для дальнейшего использования.

Проблема в том, что я не хочу вспоминать свои собственные трансляции. Я думал, что в теории это будет легко сделать - просто узнайте локальный ip и сравните с тем, что вы получите в recvfrom.

Однако мне было трудно получить локальный IP: getaddrinfo с NULL возвращает 127.0.0.1, getaddrinfo с именем хоста возвращает публичный ip. Кто-нибудь может указать мне в направлении поиска фактического IP подсети? Я думаю, что я, должно быть, упускаю что-то очень очевидное здесь, но хорошо ... Я все еще скучаю по этому :)

Примечание. Я читал другие вопросы SO о широковещании, в частности этот: UDP-Broadcast на всех интерфейсах , но я еще не дошел до проблемы с несколькими интерфейсами.

Ответы [ 5 ]

7 голосов
/ 19 ноября 2009

Что ж, при запуске вы могли бы передать другое сообщение со случайным (но отслеживаемым) значением, а затем подождать, пока это сообщение не обнаружит ваш собственный адрес, с этого момента вы можете отправлять обычные сообщения, игнорируя полученные сообщения. 1001 *

1 голос
/ 19 ноября 2009

В linux вы можете получить IP-адрес данного интерфейса, используя ioctl с опцией SIOCGIFADDR. Я не думаю, что это работает для Windows, хотя. Для этого вам нужно сделать что-то глупое, как this .

1 голос
/ 19 ноября 2009

getsockname ( документация по функциям ) может обнаружить локальный IP-адрес, связанный с конкретным сокетом. Если вы вызываете это в сокете, который используете для отправки трансляции, вы должны увидеть тот же IP-адрес, который вы увидите возвращенным recvfrom.

0 голосов
/ 01 сентября 2017

(я предполагаю, что вы работаете в 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 представителей, поэтому я не знаю, смогу ли я ответить на вопросы, спасибо Stackoverflow!)

0 голосов
/ 19 ноября 2009

Поиск параметров Scoket и посмотреть, работают ли они: IP_MULTICAST_LOOP, IP_BLOCK_SOURCE

...