11

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

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

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

但是,我发现很难获得本地 IP:getaddrinfo使用 NULL 返回127.0.0.1getaddrinfo使用主机名返回公共 ip。谁能指出我找到实际子网 ip 的方向?我想我一定在这里遗漏了一些非常明显的东西,但是好吧……我仍然想念它:)

注意:我已经阅读了关于广播的其他 SO 问题,尤其是这个:UDP-Broadcast on all interfaces,但我还没有解决多接口问题。

4

5 回答 5

8

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

于 2009-11-19T09:54:50.433 回答
2

在 linux 上,您可以使用带有SIOCGIFADDR选项的 ioctl 获取给定接口的 IP 地址。不过,我认为这不适用于 Windows。为此,您将不得不做一些像这样愚蠢的事情。

于 2009-11-19T19:53:48.050 回答
1

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

于 2009-11-19T15:25:29.467 回答
0

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

于 2009-11-19T09:57:19.607 回答
0

(我假设你在 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!)

于 2017-09-01T14:18:05.133 回答