简体   繁体   English

WinSock-UDP广播侦听器

[英]WinSock - UDP Broadcast Listener

I have a device which sends out data packets via the UDP broadcast address. 我有一台通过UDP广播地址发送数据包的设备。

I'm attempting to put together a winsock application to listen for these broadcast messages but ultimately, I'm not having much success setting up a UDP socket. 我试图将Winsock应用程序放在一起以侦听这些广播消息,但最终,设置UDP套接字并没有取得太大的成功。

Here's he code I have to create the socket and start the listener thread: 这是我必须创建套接字并启动侦听器线程的代码:

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;
}

This function succeeds, with the socket being set up and the thread being created. 该函数成功完成,并建立了套接字并创建了线程。

My UDP polling function is as follows: 我的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;
}

What happens during the polling thread is that recvfrom returns -1 and the WSAGetLastError reports a WSAEINVAL error - invalid argument. 轮询线程期间发生的情况是recvfrom返回-1,并且WSAGetLastError报告WSAEINVAL错误-无效参数。

Some code examples I've seen use the bind method but as far as I was aware, I don't need to call bind on a broadcast address. 我已经看到一些代码示例使用bind方法,但是据我所知,我不需要在广播地址上调用bind One thing I have considered is whether the sockaddr_in struct was assigned correctly - for example, does the port number need to be passed as htons(port) or just as is? 我考虑过的一件事是,是否正确分配了sockaddr_in结构-例如,是否需要将端口号作为htons(port)或原样传递?

Ok, so the issue was with this line of code, specifically the last two parameters: 好的,问题出在这行代码,特别是最后两个参数:

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

length was never being initialized (should be sizeof(sockaddr_in) ) and &socket should be a different sockaddr_in struct - not the one used during the bind call. 从未初始化过length (应该为sizeof(sockaddr_in) ),并且&socket应该是不同的sockaddr_in结构-而不是在bind调用期间使用的结构。

Sorry guys, overlooked that! 抱歉,大家忽略了!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM