weblar83
weblar83

Reputation: 731

WinSock - UDP Broadcast Listener

I have a device which sends out data packets via the UDP broadcast address.

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.

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:

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.

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. 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?

Upvotes: 2

Views: 3089

Answers (1)

weblar83
weblar83

Reputation: 731

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.

Sorry guys, overlooked that!

Upvotes: 1

Related Questions