Freigeben über


UDP and Windows 8 apps

The Windows 8 app I’m currently working on requires me to send some data over a wireless network using UDP. This is usually done by using the Socket class contained in the System.Net.Sockets namespace. However, this isn’t supported in Windows RT, which replaces the behavior of Socket with several equivalent classes. The class used for UDP is DatagramSocket. While the code using DatagramSocket is relatively short and simple, there are some intricacies involved in getting it to function properly, so in this post I’ll make things simpler by providing a working example.

At a conceptual level, the steps required to open a UDP connection and send data are very simple:

1. Create a local socket.

2. Connect to a remote host.

3. Send data to the remote host.

The code itself is short, so let’s break it down line-by-line. Bonus points if you can guess what I’m working on from the IP address and port numbers!

Creating the local socket

The first step is creating the socket, in this case a DatagramSocket:

 DatagramSocket udpSocket = new DatagramSocket();

One advantage of DatagramSocket is that I don’t have to specify what kind of protocol I want to use, because it sends exclusively UDP packets.

Next I need to bind the socket to a local port, which specifies which port you want the UDP packets to originate from. This is done by calling the DatagramSocket.BindServiceNameAsync() method. In my case, I’ll be using the port number 5556:

 await udpSocket.BindServiceNameAsync(“5556”);

It’s as simple as passing a string containing the port number. I use the await keyword here because BindServiceNameAsync() is an asynchronous method. For more documentation on the await keyword and Windows RT Tasks, check the resources at the end of the article.

Connecting to a remote host

The second step is to open a connection to a remote host. In this example I want to connect to the IP address 192.168.1.1, but the DatagramSocket.ConnectAsync() method takes an instance of the HostName class as an argument. So first I need to create a new HostName to represent the remote host:

 HostName remoteHost = new HostName(“192.168.1.1”);

Again, the argument I’m passing is a string containing the IP address or URL I want to connect to. I can then open the connection by calling ConnectAsync and passing the HostName I just created and the port I want to send data to on the remote host:

 await udpSocket.ConnectAsync(remoteHost, “5556”);

Sending data to the remote host

Once the connection is established, it’s time to send data. The DatagramSocket class doesn’t contain any methods for sending packets, so I need to use the aptly-named DataWriter class. The first step of sending data is to create a new DataWriter, passing it the OutputStream property of my DatagramSocket, udpSocket:

 DataWriter udpWriter = new DataWriter(udpSocket.OutputStream);

Now, say I want to send the string “juncti juvant” to the remote host. DataWriter doesn’t have any single method to handle this operation; sending data is a two part process. First I need to write the data to the OutputStream:

 udpWriter.WriteString(“juncti juvant”);

Check out the documentation on the DataWriter class to see what other kinds of data you can write.

The data isn’t heading to the remote host yet; now I need to actually make the DataWriter send a UDP packet. To do this I call the DataWriter.StoreAsync() method:

 await udpWriter.StoreAsync();

And with that, a UDP packet containing the payload “juncti juvant” is on its way to the remote host!

My combined code to send a UDP packet consists of the following:

 // Create a new socket and bind it to a local port
DatagramSocket udpSocket = new DatagramSocket();
await udpSocket.BindServiceNameAsync(“5556”);

// Open a connection to a remote host
HostName remoteHost = new HostName(“192.168.1.1”);
await udpSocket.ConnectAsync(remoteHost, “5556”);

// Send a data string to the remote host in a UDP packet
DataWriter udpWriter = new DataWriter(udpSocket.OutputStream);
udpWriter.WriteString(“juncti juvant”);
await udpWriter.StoreAsync();
  

Resources

DatagramSocket: https://msdn.microsoft.com/en-us/library/windows/apps/windows.networking.sockets.datagramsocket.aspx

HostName: https://msdn.microsoft.com/en-us/library/windows/apps/windows.networking.hostname.aspx

DataWriter: https://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.streams.datawriter.aspx

await keyword and Tasks: https://msdn.microsoft.com/en-us/library/hh156528.aspx


Comments

  • Anonymous
    September 12, 2012
    Just to make sure I understand, is this class available from the Windows RT environment?

  • Anonymous
    September 13, 2012
    Yes, it's available in the RT environment!

  • Anonymous
    January 15, 2013
    How do know what exceptions could be thrown, for example if the address were in use when: BindServiceNameAsync()

  • Anonymous
    January 23, 2013
    As far as I know, that information isn't listed in any central place. The code example at the bottom of the following link will give you an idea of how to deal with that method throwing exceptions msdn.microsoft.com/.../jj635238.aspx