2017-07-19 147 views
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)传递,或者正如?

+0

当然,您应该总是使用'htons()'来解决可移植性问题,该函数将根据运行代码的机器执行所需的转换。但是如果你在X86架构上使用它,你必须使用'htons()'**,因为网络字节顺序几乎总是big_endian。 –

+0

@Frankie_C,在这种情况下,我应该在指定sin_addr时使用'htonl'吗?无论哪种方式,我仍然无法接收UDP广播数据包。 – weblar83

+0

看看这里:https://stackoverflow.com/questions/41022253/udp-winsock-not-receiving-broadcast-packets,http://www.binarytides.com/udp-socket-programming-in-winsock/ –

回答

0

好了,问题是这一行的代码,特别是最后两个参数:

err = recvfrom(m_iSocket, ucBuffer, BUFFER_LEN, 0, (struct sockaddr *)&socket, &length); 

length从未被初始化(应该是sizeof(sockaddr_in))和&socket应该是一个不同的sockaddr_in结构 - 而不是一个在bind调用中使用。

对不起大家,忽略了!