c++socketsudprecvfrom

Unable to receive UDP broadcast messages


I am trying to put together a UDP monitor. I thought this would be straight forward, but everything I have tried has failed to work.

Currently, I am working with a Microsoft code example. Due to my past failed attempts, I just copied the website's code and changed the port number (see below), but I am still unable to receive the datagrams.

#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();

Using Wireshark, I see messages coming in as expected (source IP address is 10.1.1.150) Wireshark capture

I have added rules to my Windows 10 firewall to make sure that port 18190 is open and won't reject messages coming in or going out on that port.

Many websites state that for clients you shouldn’t bind the socket, but if I don’t bind the socket then recvfrom() returns immediately with -1 and the error WSAEINVAL, which states that, “An invalid argument was supplied.”

Note: I want to use recvfrom() instead of recv(), because I need sender address information.

Can anyone help me understand why this code doesn't receive the broadcasted UDP datagrams?

Update

I tried sending a message via sendto() before calling recvfrom(). Wireshark shows that the message was sent to 10.1.1.150, but recvfrom() still doesn’t get anything (i.e. it just blocks forever).

Update 2

With using the code above, if I set my computer to have a static IP address to 10.1.1.255, then I am able to receive the packets. This tells me that the code is able to receive packets, but still doesn't explain why I am unable to receive broadcasted packets.


Solution

  • So I finally found the problem, it was dumb. I post the solution here to maybe help someone else.

    My subnet mask was defaulted to 255.0.0.0, which is incorrect to get a broadcast packet. Changing the subnet mask to 255.255.255.0 allows the code to get broadcast packets.