Multicast UPnP - The definitive pattern RRS feed

  • Question

  • Although this question pertains to testing on a Surface it's actually about the general pattern for listening for and sending to multicast addresses, I figured I'd get more expertise on the ideal pattern from a desktop development group simply because there are more of you.

    I'm developing a UPnP API in C#, in fact it has been working very well until Windows 8.1 was installed on a test Surface Pro tablet.

    The nature of the failure is very odd - so what I want to do is review my design pattern to make sure it is 100% correct - its conceivable it was incorrect before but "just worked" and now 8.1 may have tightened up some issues that are exposing a flaw in my design.

    With UPnP the devices on a network "listen" for datagrams to be multicast - if they receive a search message they reply with a short device info message.

    Additionally when a UPnP device is added to a network (e.g. switched from off to on etc) it sends (via multicast) a similar device info message.

    Now the UPnP API revolves around a Topology class - we create an instance of that and invoke Search() this sends a single search message to the std IP address on which all devices are "listening".

    In addition the Topology object itself "listens" on the same multicast IP so that it can become aware of devices added to the network.

    What is not clear to me is this - I currently use TWO DatagramSockets for this - one is bound to the local machine's IP and an arbitrary port and is used to send ("multicast") datagrams to the, 1900 endpoint.

    The other socket is bound the local machine's IP and port 1900 and is used to receive device messages from newly added devices (which always multicast their presence when they are first added).

    Each socket uses the same async message receive event handler.

    So I have two DatagramSocket objects - each uses the same MessageReceived event handler.

    Here is the initialization code:

    await multicast_send_socket.BindEndpointAsync(null, String.Empty); // used to send to devices listening for search requests
    await multicast_recv_socket.BindEndpointAsync(null, multicast_port); // used to receive multicasts from new devices.

    The code that sends search messages does this:

    // Uses,1900

    stream = await multicast_send_socket.GetOutputStreamAsync(IPAddress, Port); await stream.WriteAsync(reqBuff.AsBuffer());

    The "send" socket is therefore used to send search messages and receive each device's response to them and the "recv" socket is used solely to receive info messages from added devices (which are sending via multicast).

    This is pretty much it - but the GetOutputStreamAsync above fails when running on the Surface Pro via WiFi - it doesnt fail when run on my Win 8.1 desktop under "Simulator". (Yes this is a Store app).

    So is this in fact the correct pattern? Must I use two sockets? can it or should it be done with one socket? The exception is a System.Exception and I see an exception message of "No such host is known" when I call that Get output stream.

    If I comment out the Bind and Join operations above the code runs fine on the Surface but of course it never sees messages from devices that are added or switched off/on.

    Any suggestions or ideas much appreciated.


    Tuesday, November 5, 2013 2:56 PM