After spending better part of the night, I haven't been able to make it work. Here is what I'm doing:
- This is a network game that is hosted by one participant and joined by other players. The host himself acts as a player too.
- User clicks "Host" button to start advertising on UDP.
- Other users can see the list of all available hosts and select one to join.
As a starter, I downloaded NetworkHelper library to study how networking work in UWP. This library provides UDPManager
and UDPParticipant
classes that I used for my Host
and Player
classes respectively.
The library includes a small question/answer game sample too. The only major change between my architecture and the game is that one of my players needs to act as both Host and Player, whereas the sample game can act either as host or player at a time. So unlike them, I need to have two DatagramSocket
objects listening at the same time.
Everything works fine, except (grrr... why this except is always around the corner) that the client running on the host machine can't listen to advertisement messages. DatagramSocket
tells me that I can't have multiple usages for the same network address (protocol/host/port). If I use different ports for server and client (AdvertiserPort
and ListenerPort
below), there is no exception, but the client never receives the advertisement message.
Here's the server (including relevant code only):
AdvertiserSocket = new DatagramSocket();
AdvertiserSocket.MessageReceived += MessageToConnectReceivedFromParticipantAsync;
await AdvertiserSocket.BindServiceNameAsync(AdvertiserPort);
_timer = new Timer(async state => await SendMessageAsync(), null, 0, AdvertiserInterval);
and the advertisement:
private async Task SendMessageAsync()
{
Stream outStream = (await AdvertiserSocket.GetOutputStreamAsync(AdvertiserGroupHost, AdvertiserPort)).AsStreamForWrite();
using (var writer = new StreamWriter(outStream))
{
await writer.WriteLineAsync(AdvertiserMessage);
await writer.FlushAsync();
}
}
Here is the client:
_listenerSocket = new DatagramSocket();
_listenerSocket.MessageReceived += AdvertisementMessageReceivedFromManagerAsync;
await _listenerSocket.BindServiceNameAsync(ListenerPort);
_listenerSocket.JoinMulticastGroup(ListenerGroupHost);
What am I doing wrong here? Is it possible to have a UDP advertiser and listener running on the same machine? If yes, do I use same or different ports for each?
On a side note, the library uses 237.1.3.37
as UDP_MULTICAST_IP
. Is that correct? I read somewhere that I need to use 255.255.255.255
for broadcasting advertisements. Yes?
Figured it out with the help of MS guy. This seems to be a bug in
DatagramSocket
class. You need to send at least one message on the multicast group before you start receiving multicast data from other advertisers. As a workaround, you can send an empty message before you start listening. More details and sample code can be found on this SO post (which is an absolutely simplified version of this question).Additionally, it confirmed the following:
Control.MulticastOnly
totrue
on the advertiser socket.BindServiceNameAsync()
if it is only doing multicasting.237.1.3.37
and any other address in the multicast range works for multicasting. 255.255.255.255 is not needed and shouldn't be used.Hope this helps someone down the road.