Send UDP data via broadcast

I’m working a simple UDP system for sending and receiving broadcast packets. The receiving portion is working fine, however I’m unable to send anything. I’m currently using a single socket for both actions but I’ve tried two sockets as well. The problem is winsock always returns SE_ENOTCONN but a broadcast shouldn’t require a connection right?

I’ve tried calling SetBroadcast() on the socket before the send, and I’ve tried to set a multicast using both multicast options. None of them seem to make a difference. I’m sure this is just something in my conflagration that’s wrong but I can’t for the life of me figure out what it is.

Here is the code:

bool UUDPController::InitializeController(int32 UDPListenPort)
{
	int32 BufferSize = 2 * 1024 * 1024;
	Socket = FUdpSocketBuilder(TEXT("UDP Socket"))
		.AsReusable()
		.AsNonBlocking()
		.WithBroadcast()
		.WithSendBufferSize(BufferSize)
		.WithReceiveBufferSize(BufferSize)
		.BoundToAddress(FIPv4Address::Any)
		.BoundToEndpoint(FIPv4Endpoint::Any)
		.BoundToPort(UDPListenPort)
		.Build();

	if (Socket)
	{
		UDPRecevier = new FUdpSocketReceiver(Socket, FTimespan(0, 0, 0, 0, 100), TEXT("UDP Socket"));
		UDPRecevier->OnDataReceived().BindUObject(this, &UUDPController::DataReceived);
		UDPRecevier->Start();
		return true;
	}
	return false;
}

bool UUDPController::Broadcast(const FArrayWriter& Writer)
{
	if (Socket != nullptr)
	{
		int32 BytesSent;
		Socket->Send(Writer.GetData(), Writer.Num(), BytesSent);
		if (BytesSent == Writer.Num())
		{
			return true;
		}
		else
		{
		  ESocketErrors ErrorCode = ISocketSubsystem::Get()->GetLastErrorCode();
		  UE_LOG(OpenDIS, Warning, TEXT("(%i) Failed to send %i bytes of data.  Sent %i bytes."), int32(ErrorCode), Writer.Num(), BytesSent);
		}
	}
	else
	{
		UE_LOG(MyLog, Warning, TEXT("Could not broadcast data because the socket isn't bound."));
	}

	return false;
}


void UUDPController::DataReceived(const FArrayReaderPtr& Data, const FIPv4Endpoint& FromAddress)
{
	UE_LOG(MyLog, Log, TEXT("Data Received: %i Bytes"), Data->Num());

	if (Socket)
	{
		FString TestData = TEXT("!! ACK !!");
		FArrayWriter Writer;
		Writer << TestData;
		Broadcast(Writer);
	}

}

For what it’s worth, I’ve “solved” the issue. I assumed that FIPv4Address::Any was the broadcast address but it doesn’t seem to be. So while it was listening for any packets to come in on that port, it wouldn’t send anything out because the bound to address wasn’t a broadcast address? Maybe? It’s a little unclear.

The solution was to create an FInternetAddr and call SetBroadcastAddress() on it. Then change the Send to a SendTo using that address. But it begs the question, and maybe this is my lack of understand of the UDP protocol, but shouldn’t Any set it to 255.255.255.255 and isn’t that the broadcast address?

	// Setup the address to broadcast to when sending
	BroadcastAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
	BroadcastAddr->SetBroadcastAddress();
	BroadcastAddr->SetPort(UDPListenPort);
.
.
.

	Socket->SendTo(Writer.GetData(), Writer.Num(), BytesSent, *BroadcastAddr);

If you look into the source code of Ipv4Address, it says that FIPv4Address::Any is bound to 0.0.0.0 which is the wildcard address.

The broadcast address is defined in FIPv4Address::LanBroadcast, as the comment says: “Defines the broadcast address for the ‘zero network’ (i.e. LAN), which is 255.255.255.255.”.

PS: I’m currently using 4.17 but I’m assuming it did not change.