无法接收 UDP 广播消息
Unable to receive UDP broadcast messages
我正在尝试组装一个 UDP 监视器。我以为这会很简单,但我尝试过的一切都失败了。
目前,我正在与 Microsoft code example 合作。由于我过去的尝试失败,我只是复制了网站的代码并更改了端口号(见下文),但我仍然无法接收数据报。
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
int iResult = 0;
WSADATA wsaData;
SOCKET RecvSocket;
sockaddr_in RecvAddr;
unsigned short Port = 18190;
char RecvBuf[1024];
int BufLen = 1024;
sockaddr_in SenderAddr;
int SenderAddrSize = sizeof (SenderAddr);
//-----------------------------------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup failed with error %d\n", iResult);
return 1;
}
//-----------------------------------------------
// Create a receiver socket to receive datagrams
RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (RecvSocket == INVALID_SOCKET) {
wprintf(L"socket failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Bind the socket to any address and the specified port.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
iResult = bind(RecvSocket, (SOCKADDR *) &RecvAddr, sizeof (RecvAddr));
if (iResult != 0) {
wprintf(L"bind failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Call the recvfrom function to receive datagrams
// on the bound socket.
wprintf(L"Receiving datagrams...\n");
iResult = recvfrom(RecvSocket,
RecvBuf, BufLen, 0, (SOCKADDR *) &SenderAddr, &SenderAddrSize);
if (iResult == SOCKET_ERROR) {
wprintf(L"recvfrom failed with error %d\n", WSAGetLastError());
}
//-----------------------------------------------
// Close the socket when finished receiving datagrams
wprintf(L"Finished receiving. Closing socket.\n");
iResult = closesocket(RecvSocket);
if (iResult == SOCKET_ERROR) {
wprintf(L"closesocket failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Clean up and exit.
wprintf(L"Exiting.\n");
WSACleanup();
使用 Wireshark,我看到消息按预期传入(源 IP 地址是 10.1.1.150)
我已经在我的 Windows 10 防火墙中添加了规则,以确保端口 18190 处于打开状态并且不会拒绝通过该端口传入或传出的消息。
许多网站声明,对于客户端,您不应该绑定套接字,但如果我不绑定套接字,那么 recvfrom()
returns 立即出现 -1 和错误 WSAEINVAL
,其中指出,“提供了无效参数。”
注意:我想使用recvfrom()
而不是recv()
,因为我需要发件人地址信息。
谁能帮我理解为什么这段代码收不到广播的 UDP 数据报?
更新
我尝试在致电 recvfrom()
之前通过 sendto()
发送消息。 Wireshark 显示消息已发送到 10.1.1.150,但 recvfrom()
仍然没有收到任何东西(即它只是永远阻塞)。
更新 2
使用上面的代码,如果我将我的计算机设置为静态 IP 地址为 10.1.1.255,那么我就可以接收数据包。这告诉我代码能够接收数据包,但仍然没有解释为什么我无法接收广播数据包。
所以我终于找到了问题所在,很笨。我 post 此处的解决方案可能会帮助其他人。
我的子网掩码默认为255.0.0.0,这是不正确的广播包。将子网掩码更改为 255.255.255.0 允许代码获取广播数据包。
我正在尝试组装一个 UDP 监视器。我以为这会很简单,但我尝试过的一切都失败了。
目前,我正在与 Microsoft code example 合作。由于我过去的尝试失败,我只是复制了网站的代码并更改了端口号(见下文),但我仍然无法接收数据报。
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
int iResult = 0;
WSADATA wsaData;
SOCKET RecvSocket;
sockaddr_in RecvAddr;
unsigned short Port = 18190;
char RecvBuf[1024];
int BufLen = 1024;
sockaddr_in SenderAddr;
int SenderAddrSize = sizeof (SenderAddr);
//-----------------------------------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup failed with error %d\n", iResult);
return 1;
}
//-----------------------------------------------
// Create a receiver socket to receive datagrams
RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (RecvSocket == INVALID_SOCKET) {
wprintf(L"socket failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Bind the socket to any address and the specified port.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
iResult = bind(RecvSocket, (SOCKADDR *) &RecvAddr, sizeof (RecvAddr));
if (iResult != 0) {
wprintf(L"bind failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Call the recvfrom function to receive datagrams
// on the bound socket.
wprintf(L"Receiving datagrams...\n");
iResult = recvfrom(RecvSocket,
RecvBuf, BufLen, 0, (SOCKADDR *) &SenderAddr, &SenderAddrSize);
if (iResult == SOCKET_ERROR) {
wprintf(L"recvfrom failed with error %d\n", WSAGetLastError());
}
//-----------------------------------------------
// Close the socket when finished receiving datagrams
wprintf(L"Finished receiving. Closing socket.\n");
iResult = closesocket(RecvSocket);
if (iResult == SOCKET_ERROR) {
wprintf(L"closesocket failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Clean up and exit.
wprintf(L"Exiting.\n");
WSACleanup();
使用 Wireshark,我看到消息按预期传入(源 IP 地址是 10.1.1.150)
我已经在我的 Windows 10 防火墙中添加了规则,以确保端口 18190 处于打开状态并且不会拒绝通过该端口传入或传出的消息。
许多网站声明,对于客户端,您不应该绑定套接字,但如果我不绑定套接字,那么 recvfrom()
returns 立即出现 -1 和错误 WSAEINVAL
,其中指出,“提供了无效参数。”
注意:我想使用recvfrom()
而不是recv()
,因为我需要发件人地址信息。
谁能帮我理解为什么这段代码收不到广播的 UDP 数据报?
更新
我尝试在致电 recvfrom()
之前通过 sendto()
发送消息。 Wireshark 显示消息已发送到 10.1.1.150,但 recvfrom()
仍然没有收到任何东西(即它只是永远阻塞)。
更新 2
使用上面的代码,如果我将我的计算机设置为静态 IP 地址为 10.1.1.255,那么我就可以接收数据包。这告诉我代码能够接收数据包,但仍然没有解释为什么我无法接收广播数据包。
所以我终于找到了问题所在,很笨。我 post 此处的解决方案可能会帮助其他人。
我的子网掩码默认为255.0.0.0,这是不正确的广播包。将子网掩码更改为 255.255.255.0 允许代码获取广播数据包。