Metro Nuggets
Bitesized tidbits for building Modern (Metro) apps.
How to Send and Receive a UDP Broadcast in Windows Phone 8 (and Win8)
March 18, 2013
Posted by on I’m sure you’ve seen plenty of mobile apps that do a search for a device on the network (say a bluray player) and it magically finds your device on your network. Looks pretty cool, right? Would be great to add that into your app wouldn’t it. Well, as long as you’re not developing for Windows Phone 7, then I will show how.
The Solution
As mentioned, this is only for Windows Phone 8 and Windows 8 as Windows Phone 7 doesn’t support receiving from a UDP broadcast, you can send the message out, but you won’t get any of the responses; you’d need to do a multicast communications for WP7.
So then, the code. This bit of code magically works on both Windows Phone 8 and Windows 8 without any alteration, gotta love that shared networking stack, right!
private async Task SendMessage(string message, int port) { var socket = new DatagramSocket(); socket.MessageReceived += SocketOnMessageReceived; using (var stream = await socket.GetOutputStreamAsync(new HostName("255.255.255.255"), port.ToString())) { using (var writer = new DataWriter(stream)) { var data = Encoding.UTF8.GetBytes(message); writer.WriteBytes(data); writer.StoreAsync(); } } } private async void SocketOnMessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args) { var result = args.GetDataStream(); var resultStream = result.AsStreamForRead(1024); using (var reader = new StreamReader(resultStream)) { var text = await reader.ReadToEndAsync(); Deployment.Current.Dispatcher.BeginInvoke(() => { // Do what you need to with the resulting text // Doesn't have to be a messagebox MessageBox.Show(text); }); } }
That’s all you need to do. Really, it is.
SL
Pingback: How to Send and Receive a UDP Broadcast in Windows Phone 8 (and Win8)
Thanks for this snippet of code, Works great on some windows phone 8 code I am trying. How long does the receive process last for? I have sent a SSDP request and seem to receive all the data but is the app always listening?
I think it’s always listening, not too sure to be absolutely honest.
Where is the windows.networking DLL and how do I add it to a WP8 app? I can’t find it anywhere!!
You shouldn’t need to add anything, it’s part of the .net for Windows Phone references.
Thank you for sharing
I’m sorry for bothering you but would you please ask my question below?
Is it also possible to receive unicast UDP packets? Or just broadcast receiving is supported?
Thank you very much
Regards
I’ve tried your Solution but it does not appear to send anything over the Network. I am listening with wireshark. ID_CAP_NETWORKING is checked. Any ideas?
Thank you.
Hi. Thank you for sharing the code.
Can you please tell me how the listener works? I tried different things it doens’t work for me. On which port is it listening? And it starts listening first, when I first sendet a message to broadcast right?
Thanks in advance.
The port is whatever you want it to be, but it must be the one the server end is listening out for. So if you have something listening on port 666, you should broadcast out to port 666.
Sorry if I asked wrong… I mean there is the SocketOnMessageReceived-method. Isn’t it waiting for a reply? I don’t know how to use this method. I can send out messages from the Windows Phone to a udp-server port 666. The message is received correctly. Then I try to reply from the server and send “hello” to the Windows Phone. But nothing happens in the App. I hoped that a messagebox appears with “hello” in it.
Yes, it is waiting for a response. It won’t just show a messagebox unless you’ve told it to. If you have used the code above then it should. If you put a break point in the received handler, does it get hit?
I use the code above. The received handler does not hit the breakpoint…
Where are you putting the break point?
This is my Code. I added a comment with breakpoint. I also added a MessageBox that should appear when the Received-Event is triggered but nothing happens.
I wasn’t sure if my udp packed was correctly send to the Phone but I sniffed it an it is send correctly.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using AsyncUDP.Resources;
using System.Threading.Tasks;
using Windows.Networking.Sockets;
using System.Text;
using Windows.Networking;
using System.IO;
using Windows.Storage.Streams;
namespace AsyncUDP
{
public partial class MainPage : PhoneApplicationPage
{
int i = 0;
public MainPage()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
SendMessage(“Hello “+ i + “\n”, 1337);
i++;
}
private async Task SendMessage(string message, int port)
{
var socket = new DatagramSocket();
socket.MessageReceived += SocketOnMessageReceived;
using (var stream = await socket.GetOutputStreamAsync(new HostName(“255.255.255.255”), port.ToString()))
{
using (var writer = new DataWriter(stream))
{
var data = Encoding.UTF8.GetBytes(message);
writer.WriteBytes(data);
writer.StoreAsync();
}
}
}
private async void SocketOnMessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
//BREAK POINT
MessageBox.Show(“Received a Message!”);
var result = args.GetDataStream();
var resultStream = result.AsStreamForRead(1024);
using (var reader = new StreamReader(resultStream))
{
var text = await reader.ReadToEndAsync();
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(text);
});
}
}
}
}
Could it be because it’s not being awaited? Try putting async before the void of your button handler, then put an await before the sendmessage.
I added async and await but that wasn’t the reason. I think I have to do some research to fix out the problem.
Thank you very much so far for your quick response 🙂 .
For reference, this is how I’m using it https://github.com/MediaBrowser/MediaBrowser.WindowsPhone/blob/7e45c4fa90d4def5762813009946717c84d12943/MediaBrowser.WindowsPhone8/ViewModel/SettingsViewModel.cs#L343
i cannot use Deployment.Current.Dispatcher.BeginInvoke(() . It gives me error name Deployment could not be found in current context. ? please help;
Try this . It is working well.
tb1 & tb2 are TextBox and bt1 is “Send” button.
Not running on the same machine but if you use Hyper-V, it can communicate very easily. Virtual PC is Win Server 2008 and .Net UDPClient running program uses Windows Form. You can get it here:
http://www.dreamincode.net/forums/topic/231058-peer-to-peer-chat-advanced/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace ChatTestStore2
{
public sealed partial class MainPage : Page
{
DatagramSocket socket = new DatagramSocket();
int port;
public MainPage()
{
this.InitializeComponent();
port = 54545;
StartListener(port);
}
private async void StartListener( int port)
{
socket.MessageReceived += SocketOnMessageReceived;
await socket.BindServiceNameAsync(port.ToString());
}
private async Task SendMessage(string message, int port)
{
using (var stream = await socket.GetOutputStreamAsync(new HostName(“255.255.255.255″), port.ToString()))
{
using (var writer = new DataWriter(stream))
{
var data = Encoding.UTF8.GetBytes(message);
writer.WriteBytes(data);
await writer.StoreAsync();
}
}
}
private async void SocketOnMessageReceived(DatagramSocket soket, DatagramSocketMessageReceivedEventArgs eventArguments)
{
// si asta e ff bun
var result = eventArguments.GetDataStream();
var resultStream = result.AsStreamForRead(1024);
using (var reader = new StreamReader(resultStream))
{
string text = await reader.ReadToEndAsync();
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
tb2.Text = text;
// Do what you need to with the resulting text
});
}
/*
// this work as well
try
{
uint stringLength = eventArguments.GetDataReader().UnconsumedBufferLength;
string command = eventArguments.GetDataReader().ReadString(stringLength);
await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
tb2.Text = command + ” ( ” + DateTime.Now +”)”;
// MakeMove(command);
}
);
}
catch (Exception exception)
{
SocketErrorStatus socketError = SocketError.GetStatus(exception.HResult);
if (socketError == SocketErrorStatus.ConnectionResetByPeer)
{
Debug.WriteLine(“Peer does not listen on the specific port. Please make sure that you run step 1 first ” +
“or you have a server properly working on a remote server.”);
}
else if (socketError != SocketErrorStatus.Unknown)
{
Debug.WriteLine(“Error happened when receiving a datagram: ” + socketError.ToString());
}
else
{
throw;
}
}
*/
}
private async void bt1_Click(object sender, RoutedEventArgs e)
{
await SendMessage(“Me: \n”+tb1.Text,port);
}
}
}
Just to pull out the minimum change required, the below two lines of code are the change required to make the listener MessageReceived events fire.
socket.MessageReceived += SocketOnMessageReceived;
await socket.BindServiceNameAsync(port.ToString());<====== this binds the socket for incoming data.