我在PC上有一个应用程序应该从本地网络上的设备获取一些UDP广播消息。
设备定期向其子网发送UDP广播消息,应用程序应该能够接收这些广播。当PC和设备位于同一子网中时,接收这些消息没有问题。
但是,当我将设备和PC放置在不同的子网中时,我无法再在PC应用程序中接收设备的广播,但我可以在wireshark中看到它们。
所以,如果我有:
10.0.100.100
的PC,子网掩码为255.255.0.0
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);
}
}
然后我没有收到设备的广播消息。
但是,如果我的IP 10.0.255.222
的设备B 且子网掩码为255.255.0.0
,即使PC仍在另一个子网中,我也可以收到这些消息。< / p>
如果我使用子网掩码10.0.254.100
在255.255.255.0
处移动PC,那么我可以与设备A 进行通信,但之后我无法看到来自的消息设备B 位于10.0.255.222
。
令我困惑的是,在两种情况下,Wireshark都可以捕获数据包。
答案 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帧 相同的子网。