通过wireshark的方式接收跨子网的UDP广播数据包

时间:2015-06-24 05:12:09

标签: c networking udp wireshark broadcast

我在PC上有一个应用程序应该从本地网络上的设备获取一些UDP广播消息。

设备定期向其子网发送UDP广播消息,应用程序应该能够接收这些广播。当PC和设备位于同一子网中时,接收这些消息没有问题。

但是,当我将设备和PC放置在不同的子网中时,我无法再在PC应用程序中接收设备的广播,但我可以在wireshark中看到它们。

场景1

所以,如果我有:

  • IP 10.0.100.100的PC,子网掩码为255.255.0.0
  • IP 10.0.254.83设备A ,子网掩码为255.255.255.0
  • 这个概念验证PC应用程序:

    #ifndef WIN32_LEAN_AND_MEAN
    #define WIN32_LEAN_AND_MEAN
    #endif
    
    #include <windows.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <iphlpapi.h>
    #include <stdio.h>
    #include <assert.h>
    
    #pragma comment(lib, "Ws2_32.lib")
    int main()
    {
        WSADATA wsaData;
    
        int iResult;
    
        iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
        if (iResult != 0) {
            printf("WSAStartup failed: %d\n", iResult);
            return 1;
        }
        sockaddr_in si_me, si_other;
        int s;
        assert((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1);
        int port = 32002;
        BOOL broadcast = TRUE;
    
        setsockopt(s, SOL_SOCKET, SO_BROADCAST,
            (char*)&broadcast, sizeof(broadcast));
    
        memset(&si_me, 0, sizeof(si_me));
        si_me.sin_family = AF_INET;
        si_me.sin_port = htons(port);
        si_me.sin_addr.s_addr = INADDR_ANY;
    
        assert(bind(s, (sockaddr *)&si_me, sizeof(sockaddr)) != -1);
    
        while (1)
        {
            char buf[10000];
            memset(buf, 0, 10000);
            int slen = sizeof(sockaddr);
            recvfrom(s, buf, sizeof(buf)-1, 0, (sockaddr *)&si_other, &slen);
    
            char *ip = inet_ntoa(si_other.sin_addr);
    
            printf("%s: %s\n", ip, buf);
        }
    }
    

然后我没有收到设备的广播消息。

场景2

但是,如果我的IP 10.0.255.222设备B 且子网掩码为255.255.0.0,即使PC仍在另一个子网中,我也可以收到这些消息。< / p>

场景3

如果我使用子网掩码10.0.254.100255.255.255.0处移动PC,那么我可以与设备A 进行通信,但之后我无法看到来自的消息设备B 位于10.0.255.222

令我困惑的是,在两种情况下,Wireshark都可以捕获数据包。

  1. 为什么我的应用程序看不到来自设备A 的数据包以及为什么wireshark可以(在第一种情况下)?我可以做些什么类似wireshark所以我可以看到那些数据包?
  2. 情景 2 3 背后的解释是什么? 由于方案2 设备B 明显位于另一个子网中,但通信丢失仅发生在方案3
  3. 我应该阅读什么才能更好地了解这些问题?
  4. PS:我认为问题不在于UDP的不可靠性。 PPS:我确实尝试禁用“在混杂模式下捕获数据包”,结果是一样的,我可以在Wireshark中看到来自设备A 的数据包

3 个答案:

答案 0 :(得分:1)

有一点是 - Wireshark使用混杂模式 - 因此它可以读取交换机端口上的任何内容。这可能包括您自己的广播,一些其他广播,甚至一些不适合您的单播/多播 - 只要数据包到达该交换机端口。您的计划不是这种情况。您的程序正在尝试仅接收网络广播地址的数据报。现在下面的解释会有所帮助。

我认为你混淆了网络地址和广播域名。以下是您案例中发生的事情

情景1.

PC - 10.0.100.100网络掩码255.255.0.0所以广播地址为10.0.255.255,(通常在网络掩码中为0的任何内容 - 如果设置为全部{{1} s成为广播地址。)

因此,您的应用程序将收到发送到此广播地址的任何内容。

设备A 1网络掩码10.0.254.83。所以广播地址是255.255.255.0。请注意,它与PC的广播地址不同,因此 - 您无法接收它们。

所以不要被外观相同的网络地址弄糊涂。

情景2

设备B - 10.0.254.255网络掩码10.0.255.222。所以广播地址是255.255.0.0。这与上面方案1中的PC地址相同,因此可以接收数据报(不处于混杂模式)。 (10.0.255.255部分可能看起来像一个不同的网络,但这不是因为网络掩码是16字节255.222

情景3

PC:10.0.254.100网络掩码255.255.255.0因此网络的广播地址为10.0.254.255 - 与方案1中的设备A的广播地址(255.255.0.0)相同,但与广播地址不同方案2中的设备B(10.0.254.255),因此预期结果。

在您的方案中 - 设备A的网络是设备B和PC网络的子网,广播仅限于子网。当您将PC移动到子网时,您将收到子网的广播(Senario 3)。

编辑:

解释 - 为什么你可以在wireshark中看到子网广播,为什么不在你的应用程序中看到 - 你在wireshark中看到的是你的网卡收到的任何内容。由于所有广播都有10.0.255.255的目标mac,您的卡将接收它,但您的操作系统堆栈将丢弃它们,因为网络级地址不是网络级广播。即使没有混杂模式,也会收到第2层广播。 希望有所帮助。

答案 1 :(得分:0)

Wireshark将网络适配器置于“混杂模式”,报告它在网络上看到的所有数据包。通常,它仅报告发往主机的数据包。听起来在你的情况下,网络掩码的区别意味着设备将使用不同的广播地址,并且数据包将被丢弃。

Wireshark在Windows上安装了一个特殊的网络驱动程序,以访问所有流量https://wiki.wireshark.org/WinPcap

答案 2 :(得分:0)

无论何时运行wireshark。都会自动将您的设备(接口)放入 &#34;混杂模式&#34; 。它会捕获空中的所有数据包, 没有打扰子网掩码。

而你的电脑将捕获多帧的UDP帧 相同的子网。