55

OK this is one I've been trying to figure out for a few days now. We have an application on Windows Phone 7 where phones join a multicast group and then send and receive messages to the group to talk to each other. Note - this is phone to phone communication.

Now I'm trying to port this application to Windows Phone 8 - using the 'Convert to Phone 8' feature in Visual Studio 2012 - so far so good. Until I try to test the phone to phone communication. The handsets seem to join the group fine, and they send the datagrams OK. They even receive the messages that they send to the group - however, no handset ever receives a message from another handset.

Here is the sample code behind to my page:

// Constructor
public MainPage()
{
    InitializeComponent();
}

// The address of the multicast group to join.
// Must be in the range from 224.0.0.0 to 239.255.255.255
private const string GROUP_ADDRESS = "224.0.1.1";

// The port over which to communicate to the multicast group
private const int GROUP_PORT = 55562;

// A client receiver for multicast traffic from any source
UdpAnySourceMulticastClient _client = null;

// Buffer for incoming data
private byte[] _receiveBuffer;

// Maximum size of a message in this communication
private const int MAX_MESSAGE_SIZE = 512;

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
    _client = new UdpAnySourceMulticastClient(IPAddress.Parse(GROUP_ADDRESS), GROUP_PORT);
    _receiveBuffer = new byte[MAX_MESSAGE_SIZE];

    _client.BeginJoinGroup(
        result =>
        {
            _client.EndJoinGroup(result);
            _client.MulticastLoopback = true;
            Receive();
        }, null);
}

private void SendRequest(string s)
{
    if (string.IsNullOrWhiteSpace(s)) return;

    byte[] requestData = Encoding.UTF8.GetBytes(s);

    _client.BeginSendToGroup(requestData, 0, requestData.Length,
        result =>
        {
            _client.EndSendToGroup(result);
            Receive();
        }, null);
}

private void Receive()
{
    Array.Clear(_receiveBuffer, 0, _receiveBuffer.Length);
    _client.BeginReceiveFromGroup(_receiveBuffer, 0, _receiveBuffer.Length,
        result =>
        {
            IPEndPoint source;

            _client.EndReceiveFromGroup(result, out source);

            string dataReceived = Encoding.UTF8.GetString(_receiveBuffer, 0, _receiveBuffer.Length);

            string message = String.Format("[{0}]: {1}", source.Address.ToString(), dataReceived);
            Log(message, false);

            Receive();
        }, null);
}

private void Log(string message, bool isOutgoing)
{
    if (string.IsNullOrWhiteSpace(message.Trim('\0')))
    {
        return;
    }

    // Always make sure to do this on the UI thread.
    Deployment.Current.Dispatcher.BeginInvoke(
    () =>
    {
        string direction = (isOutgoing) ? ">> " : "<< ";
        string timestamp = DateTime.Now.ToString("HH:mm:ss");
        message = timestamp + direction + message;
        lbLog.Items.Add(message);

        // Make sure that the item we added is visible to the user.
        lbLog.ScrollIntoView(message);
    });

}

private void btnSend_Click(object sender, RoutedEventArgs e)
{
    // Don't send empty messages.
    if (!String.IsNullOrWhiteSpace(txtInput.Text))
    {
        //Send(txtInput.Text);
        SendRequest(txtInput.Text);
    }
}

private void btnStart_Click(object sender, RoutedEventArgs e)
{
    SendRequest("start now");
}

In order to simply test out the UDP stack, I downloaded the sample from MSDN found here and I tested this on a pair of Windows Phone 7 devices and it works as expected. Then I converted to Windows Phone 8 and deployed to my handsets, again the devices seem to initiate their connection, and the user can enter their name. However, again the devices can't see or communicate with other devices.

Finally I implemented a simple communication test using the new DatagramSocket implementation, and again I see successful initiation, but no inter-device communication.

This is the same code behind page using the datagram socket implementation:

// Constructor
public MainPage()
{
    InitializeComponent();
}

// The address of the multicast group to join.
// Must be in the range from 224.0.0.0 to 239.255.255.255
private const string GROUP_ADDRESS = "224.0.1.1";

// The port over which to communicate to the multicast group
private const int GROUP_PORT = 55562;

private DatagramSocket socket = null;

private void Log(string message, bool isOutgoing)
{
    if (string.IsNullOrWhiteSpace(message.Trim('\0')))
        return;

    // Always make sure to do this on the UI thread.
    Deployment.Current.Dispatcher.BeginInvoke(
    () =>
    {
        string direction = (isOutgoing) ? ">> " : "<< ";
        string timestamp = DateTime.Now.ToString("HH:mm:ss");
        message = timestamp + direction + message;
        lbLog.Items.Add(message);

        // Make sure that the item we added is visible to the user.
        lbLog.ScrollIntoView(message);
    });
}

private void btnSend_Click(object sender, RoutedEventArgs e)
{
    // Don't send empty messages.
    if (!String.IsNullOrWhiteSpace(txtInput.Text))
    {
        //Send(txtInput.Text);
        SendSocketRequest(txtInput.Text);
    }
}

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
    socket = new DatagramSocket();
    socket.MessageReceived += socket_MessageReceived;

    try
    {
        // Connect to the server (in our case the listener we created in previous step).
        await socket.BindServiceNameAsync(GROUP_PORT.ToString());
        socket.JoinMulticastGroup(new Windows.Networking.HostName(GROUP_ADDRESS));
        System.Diagnostics.Debug.WriteLine(socket.ToString());
    }
    catch (Exception exception)
    {
        throw;
    }
}

private async void SendSocketRequest(string message)
{
    // Create a DataWriter if we did not create one yet. Otherwise use one that is already cached.
    //DataWriter writer;
    var stream = await socket.GetOutputStreamAsync(new Windows.Networking.HostName(GROUP_ADDRESS), GROUP_PORT.ToString());
    //writer = new DataWriter(socket.OutputStream);
    DataWriter writer = new DataWriter(stream);

    // Write first the length of the string as UINT32 value followed up by the string. Writing data to the writer will just store data in memory.
   // stream.WriteAsync(
    writer.WriteString(message);

    // Write the locally buffered data to the network.
    try
    {
        await writer.StoreAsync();
        Log(message, true);
        System.Diagnostics.Debug.WriteLine(socket.ToString());
    }
    catch (Exception exception)
    {
        throw;
    }
    finally
    {
        writer.Dispose();
    }
}

void socket_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
    try
    {
        uint stringLength = args.GetDataReader().UnconsumedBufferLength;
        string msg = args.GetDataReader().ReadString(stringLength);

        Log(msg, false);
    }
    catch (Exception exception)
    {
        throw;
    }
}

Last night I took the handsets home to test them on my home wireless network, low and behold I get successful device communication.

So to recap - my legacy Windows Phone 7 code runs fine on my work network. The port to Windows Phone 8 (no actual code change) does not send inter-device communication. This code does work on my home network. The code runs with the debugger attached and there are no signs of errors or exceptions anywhere during execution.

The handsets I'm using are:

Windows Phone 7 - Nokia Lumia 900 (* 2), Nokia Lumia 800 (* 3) Windows Phone 8 - Nokia Lumia 920 (* 1), Nokia Limia 820 (* 2)

These are all running the latest OS, and are in developer mode. Development environment is Windows 8 Enterprise running Visual Studio 2012 Professional

I cant tell you much about the work wireless network - other than the Phone 7 devices have no trouble.

As for the home wireless network i used, that's just a basic BT Broadband router with none of the 'out the box' settings altered.

Clearly there is an issue with the way that the two network are configured, but there is also very clearly an issue with the way Windows Phone 8 implements UDP messages.

Any input would be appreciated as this is driving me mad right now.

Mario S
  • 10,931
  • 24
  • 34
  • 45
Adam Stewart
  • 1,805
  • 1
  • 18
  • 25
  • 1
    The latest comment i have had from Microsoft is that this might relate to a bug in the stack. As of now i am waiting to hear back from them. I will update this post as and when i hear more. However, the WinRT implementation can be made to work, if the first line of the SendSocketRequest implementation is changed to this: `var stream = await socket.GetOutputStreamAsync(new Windows.Networking.HostName(IPAddress.Broadcast.ToString()), GROUP_PORT.ToString());` – Adam Stewart Dec 03 '12 at 15:44
  • Try using different group address like "239.0.0.11". – nucleons Dec 17 '12 at 13:10
  • Any more word from Microsoft? I am hitting the same issue and have not found a work-around. – briandunnington Dec 20 '12 at 06:54
  • I've exactly the same Problem. Do you have any new News?? – The Chris Dec 28 '12 at 15:11
  • @nucleons i haven't heard anything else from Microsoft since they confirmed that the bug was in their stack. We are using the workaround i describe above; and since it works we have moved on to our new work items. i will keep this post updated should i hear anything from MS regarding a resolution to this. – Adam Stewart Jan 02 '13 at 05:00
  • @ChrisTTian667 see latest comment i just made – Adam Stewart Jan 02 '13 at 05:00
  • I'm seeing the same thing, and also opened a support case with Microsoft. See here: http://social.msdn.microsoft.com/Forums/en-US/wpdevelop/thread/4eb2b9c1-5ada-422e-93a2-fbafe3a67491 Other users reporting this as well: http://social.msdn.microsoft.com/Forums/en-US/wpdevelop/thread/0c3888a3-90b1-4c6c-b522-0d46bdb2ea1f http://social.msdn.microsoft.com/Forums/en-US/wpdevelop/thread/58fc5a6e-2cee-4589-a6c3-d2e28faea690 Personally I haven't seen any wifi networks where this works on, so up until now I assumed this wasn't a wifi issue – dotMorten Jan 03 '13 at 22:32
  • ...btw your workaround didn't work for me. – dotMorten Jan 03 '13 at 23:20
  • @dotMorten reading your comments in the other threads i can also confirm that i still see this bug on Lumia 820s as well. Still no news from MS my end either – Adam Stewart Jan 15 '13 at 17:56
  • As per Morten's comment on the MSDN forums, this should been fixed with a firmware update published over six months ago. @AdamStewart can you confirm that's the case, and if so, close the question? – Claus Jørgensen Jul 20 '13 at 00:28
  • @ClausJørgensen I no longer have access to the code or hardware that this question related to, perhaps if someone else who experienced the issue could check this question can be closed. However you mention firmware rather than a windows software patch. I have seen this issue on Nokia Lumia 920 and 820 mobile phones and Samsung tables and as mentioned before MS had confirmed the issue was in the Windows 8 stack. – Adam Stewart Jul 22 '13 at 10:11
  • This is now out of date as UdpAnySourceMulticastClient is deprecated. I tried to do multicast using new DatagramSocet, without luck. Any idea how to multicast using new APIs? Microsoft APIs are a mess lately, changing every month almost... And documentation sucks – Daniel Gruszczyk May 09 '15 at 16:19

3 Answers3

1

I notice you use the loopback. I think it means that when you send a message from your client you will receive the message you sent also. This means your receive handler will fire. It has the effect of clearing the receive buffer in a seemingly unthreadsafe fashion. Try putting some try catch in your receive method and see if anything untoward is happening but you might instead just not use the shared receive buffer in any case.

cineam mispelt
  • 365
  • 1
  • 6
1

Have you ever tried joining another multicast group? Because 224.0.1.1 seems to be in use as of IANA assignments. You find all of the here.

Maybe on Windows Phone 8 some service is tighter bound to listen to messages coming in (e.g. a network service that is running in kernel mode) and they are never forwarded to you.

HaMster
  • 523
  • 1
  • 5
  • 17
1

UDP multicast works pretty strangely under windows phone 7 from my experience so you should checkout the same for windows phone 8.

Here is my experience:

  1. check what is officially supported, for instance under Windows Phone OS 7.1 (last OS I tried before switching), TCP unicast, UDP unicast, and UDP multicast clients are supported.
  2. some versions of Windows phone permit to receive a UDP session only if the client first opened it and the session is received within no more than 10 seconds, this seems like some sort of security thing on Windows Phone.
  3. try with different addresses: multicast addresses in the range from 224.0.0.0 to 224.0.0.255 inclusive are “well-known” reserved multicast addresses.
  4. Check both in the virtual machine and in a real phone device, the behaviour may differ.
dendini
  • 3,602
  • 9
  • 35
  • 69