4

After spending better part of the night, I haven't been able to make it work. Here is what I'm doing:

  1. This is a network game that is hosted by one participant and joined by other players. The host himself acts as a player too.
  2. User clicks "Host" button to start advertising on UDP.
  3. 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?

dotNET
  • 33,414
  • 24
  • 162
  • 251
  • I don't have an answer for you, but rather a suggestion, your game (advertising & listening) could use MQTT, which is basically simple lightweight 'PubSub' type service. It is very easy to configure, and I suspect it will prove easier to work with. Reference: [MQTT](http://mqtt.org/), and for C#: [M2Mqtt for .Net : MQTT client for Internet of Things & M2M communication](https://code.msdn.microsoft.com/windowsdesktop/M2Mqtt-MQTT-client-library-ac6d3858) and [C# .Net and WinRT Client](https://eclipse.org/paho/clients/dotnet/). – Keyur PATEL Sep 26 '16 at 07:47
  • The issue is you can't have more than one connection with the same three items 1) Source IP address, 2) Destination IP address 3) Port number. When you have both the server and client on the same machine often this error occurs because you are making two virtual connections. The solution is for the server to listen to the IP Any address, All IP being received on PC gets forwarded to IP Any which solver this issue. It has nothing to do with Muticast. The muticast error occurs when two listeners are using same IP and port on same machine. – jdweng Sep 26 '16 at 07:55
  • @KeyurPATEL: Thanks for the link. That sounds promising. I just tried the sample code on the website, but am constantly getting errors. What is `MQTT_BROKER_ADDRESS`? – dotNET Sep 26 '16 at 08:40
  • @jdweng: I wasn't able to use `IPAddress.Any` for advertising. It throws exception saying "The specified class was not found". – dotNET Sep 26 '16 at 08:41
  • @KeyurPATEL: boy. this MQTT thing requires me to install a broker server (a software service) on the machine, which in my opinion is a bit too much for simple p2p messaging. Additionally this is a UWP project, so I'll need a UWP implementation of broker, which I was not able to find. – dotNET Sep 26 '16 at 08:59
  • @dotNET It refers to the 'server' IP address. I put quotes around server since you need to install a broker and instantiate a new server, as you mentioned. However, it isn't as tedious and excessive as you think; just another library / reference and 5-6 lines more of code. For example, [HiveMQ](http://www.hivemq.com/try-out/) or [Mosquitto](https://mosquitto.org/) are both open source brokers, requiring minimal code to start your own server. I am not sure about the UWP implementation and its effects. Even if you can't use MQTT for your project, keep it in mind, its very useful. – Keyur PATEL Sep 26 '16 at 09:03
  • You can't advertise using IPadress.Any, only at the receiver. I may of confused the terms client and server. the definition of client and server are different at the application level than at the transport level. The server always starts first and listens, while the client used the connection method. The server should use Ipaddress.Any while the client used the IP address of the PC. The net library always gives an exception if the client uses IPaddress.Any with the connect method(). – jdweng Sep 26 '16 at 09:46

1 Answers1

1

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:

  1. You can have more than one sockets using the same host/port if you set Control.MulticastOnly to true on the advertiser socket.
  2. Advertiser socket does not need to call BindServiceNameAsync() if it is only doing multicasting.
  3. 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.

Community
  • 1
  • 1
dotNET
  • 33,414
  • 24
  • 162
  • 251