0
我有一个通过UDP广播地址发送数据包的设备。WinSock - UDP广播监听器
我试图放在一起一个winsock应用程序来侦听这些广播消息,但最终,我没有成功建立一个UDP套接字。
这里是他的代码我要创建套接字,并启动监听线程:
DWORD CreateStatusListener() {
WORD wVersion;
WSADATA wsa;
int err;
wVersion = MAKEWORD(2, 2);
err = WSAStartup(wVersion, &wsa);
if (err != 0) {
// Fail gracefully
// ...
}
// Create the UDP status socket
m_iSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (m_iSocket == SOCKET_ERROR) {
// Fail gracefully
// ...
}
m_bAbort = FALSE;
// Create the UDP status socket listener thread
m_hThread = CreateThread(NULL, 0, PollStatusSocket, NULL, 0, &m_dwThreadID);
if (!m_hThread) {
// Fail gracefully
// ...
}
return ERR_SUCCESS;
}
此函数成功,与插座正在建立和正在创建的线程。
我UDP轮询功能如下:
static DWORD WINAPI PollStatusSocket(LPVOID lpParam) {
struct sockaddr_in socket;
INT length;
// Set up the address struct
memset(&socket, 0, sizeof(socket));
socket.sin_family = AF_INET;
socket.sin_port = htons(52102);
socket.sin_addr.s_addr = INADDR_BROADCAST;
INT err = SOCKET_ERROR;
INT bAllow = 1;
err = setsockopt(m_iSocket, SOL_SOCKET, SO_BROADCAST, (char *)&bAllow, sizeof(bAllow));
// Allocate a receive buffer
char ucBuffer[BUFFER_LEN];
// Loop while the thread is not aborting
while (!m_bAbort) {
err = recvfrom(m_iSocket, ucBuffer, BUFFER_LEN, 0, (SOCKADDR *)&socket, &length);
if (err != SOCKET_ERROR) {
// Check we have a valid status message
// ...
}
else {
err = WSAGetLastError();
printf("Error: %d", err);
}
}
return 0;
}
轮询线程期间会发生什么是recvfrom
返回-1和WSAGetLastError
报告WSAEINVAL
错误 - 无效的参数。
我见过的一些代码示例使用bind
方法,但据我所知,我不需要在广播地址上调用bind
。我考虑过的一件事是sockaddr_in
结构是否被正确分配 - 例如,端口号是否需要作为htons(port)
传递,或者正如?
当然,您应该总是使用'htons()'来解决可移植性问题,该函数将根据运行代码的机器执行所需的转换。但是如果你在X86架构上使用它,你必须使用'htons()'**,因为网络字节顺序几乎总是big_endian。 –
@Frankie_C,在这种情况下,我应该在指定sin_addr时使用'htonl'吗?无论哪种方式,我仍然无法接收UDP广播数据包。 – weblar83
看看这里:https://stackoverflow.com/questions/41022253/udp-winsock-not-receiving-broadcast-packets,http://www.binarytides.com/udp-socket-programming-in-winsock/ –