(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Windows Phone 7.5: Using sockets

(5 votes)
Andrea Boschin
>
Andrea Boschin
Joined Nov 17, 2009
Articles:   87
Comments:   9
More Articles
3 comments   /   posted on Jan 16, 2012
Categories:   Windows Phone
Tweet

Also if the technical specifications of Windows Phone 7.0 stated that it is compatible with Silverlight 3.0, this only means that every feature you can use in the phone is available on the desktop but not viceversa. Sockets are a clear demonstration of this sentence. While they are perfectly available on Silverlight 3.0, they are locked down in the phone for the, so called, "security purposes". Curiously if you watch at the codebase of Silverlight for Windows Phone 7.0 you see that, the Socket class exists but it is declared "internal".

The new OS 7.5 have made Sockets available to developers, opening the way to a wide series of applications that uses this low-level communication way. Sockets are for sure difficult from the programming side, but they offer a connected/disconnected, fast and reliable way of exchange data that is unreplaceable for many purposes.

What sockets can do (and what they can't)

Sockets are something that we use every day. Also if we are not aware of this, they are at the very base of each network protocol, comprised HTTP, SMTP, PO3, and so on. Their purpose is to create a communication channel between two boundaries where they can send and receive something that usually is a binary message. There are two ways to create a Socket connection. The TCP and the UDP. Since TCP is an always connected protocol that is tailored to exchange continuous streams, UDP is mostly made to exchange fast and short packets of information - called datagrams - while the boundaries aren't continuously connected. To make a practical example, HTTP is based on the TCP protocol where the client and the server establish a connected channel and they both send and receive on this channel until the communication ends. On the other side, DNS is mostly UDP based because the client sends a request datagram and the server answers with another datagram but there is not a real channel established between the two boundaries. Do not underestimate UDP since it is often very effective. Infact a number of streaming protocols are based on it.

While Silverlight only supports TCP, Windows Phone 7.5 also supports UDP Sockets. I'm always really amazed about the confusion of team's choices, but to me it is really not understandable the reason that leads to diverge the sockets capabilities in this matter. But so it is. So, while in Silverlight for desktop we can only use TCP and a limited set of ports, if application is not fully trusted, with Windows Phone 7.5 we have the very full set of knifes to work with.

No matter you are using a TCP or UDP connection, a communication is ruled by the same process and by the same structures. Once you have choose the endpoint to connect to, in terms of ip address and port, the process of communications is the following:

  1. Create the Socket class
  2. Connect the socket
  3. Send and receive data
  4. Shutdown the connection

The correct sequence of operations at point 3 is determined by the network protocol you are implementing. As an example if you are placing an HTTP call, first of all you send the request and the receive the response, but there are many cases where you can simply start to receive a continuous stream because the protocol continuously broadcast packets.

All the phases of the socket connection are ruled by at least an instance of SockerAsyncEventArgs. This class contains the reference to the remote endpoint, the operation in progress/completed, the data that is sent to or received by the peer. In a simple connection you will have only a single instance but, for performance purposes (e.g. in a multithreaded environment), you can have a pool of instances to use for the various operations.

Implementing a simple UDP protocol (NTP)

For the sake of the article I will show now how to implement a simple protocol. The NTP protocol I will show, is very basic, just because I do not want to spend most of the time explaining the protocol itself. NTP stands for Network Time Protocol and despite the very simple datagram you have to exchange over an UDP socket, the RFC is really complex because of the server implementation that have to ensure redundancy and precision across multiple sources.

To make an NTP request you have to do the following:

  1. Connect to a NTP server on port 123
  2. Prepare a datagram of 48 zeroed bytes with the first byte set to 0x1b
  3. Send the datagram over UDP
  4. Receive the same datagram filled with time information
  5. Close the socket
  6. Decode and use the result

The returned bytes represents a DateTime and I do not enter in the format of the response. If you are interested simply watch at the decoding method in my example. The first thing to do is to create a NtpClient class. This class will represent a single server and is initialized with the remote endpoint:

   1: public class NtpClient
   2: {
   3:     private Socket Socket { get; set; }
   4:     private SocketAsyncEventArgs Args { get; set; }
   5:  
   6:     public NtpClient(EndPoint endPoint)
   7:     {
   8:         this.Args = new SocketAsyncEventArgs
   9:         {
  10:             RemoteEndPoint = endPoint
  11:         };
  12:  
  13:         this.Args.Completed += new EventHandler<SocketAsyncEventArgs>(Operation_Completed);
  14:     }
  15:  
  16:     private void Operation_Completed(object sender, SocketAsyncEventArgs e)
  17:     {
  18:     }
  19: }

In this first part I create an instance of the SocketAsyncEventArgs and initialize it with the RemoteEndPoint. This instance is shared by all the network calls so it is defined as a private member property. The code also attach the Completed event of this instance. Every time I will perform an action on the socket, using this instance, the Completed event is raised and the LastOperation property will be set with a value representing the action I did.

The GetNetworkTimeAsync method initializes the Socket class and initiates the connection. Under the hoods, the meaning of "ConnectAsync" is different between TCP and UDP but it has to be made for both the protocols. Here I am using an UDP connection so the values in the ctor indicate ProtocolType.Udp and a SocketType.Dgram. If I would use a TCP channel I should use SocketType.Stream and ProtocolType.Tcp.

   1: public void GetNetworkTimeAsync()
   2: {
   3:     this.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
   4:     this.Socket.ConnectAsync(this.Args);
   5: }

From this point, the lifetime of the class is governed by the Operation_Completed event. Every time I perform an action this method collects the result. So when I call connect the method receives the result, but the same happen when I call SendAsync and ReveiceAsync. Inside the Operation_Completed I create a chain of operation, always calling the following action as the result of another.

   1: private void Operation_Completed(object sender, SocketAsyncEventArgs e)
   2: {
   3:     if (e.SocketError == SocketError.Success)
   4:     {
   5:         switch (e.LastOperation)
   6:         {
   7:             case SocketAsyncOperation.Connect:
   8:                 this.SendRequest();
   9:                 break;
  10:             case SocketAsyncOperation.Send:
  11:                 this.ReceiveResponse();
  12:                 break;
  13:             case SocketAsyncOperation.Receive:
  14:                 this.ReadAndClose();
  15:                 break;
  16:         }
  17:     }
  18:     else
  19:         this.OnError(e.SocketError);
  20: }

 

The chain indicates that following the Connect I call SendRequest then ReceiveResponse and finally ReadAndClose. These decisions are wrapped from an if construct that handles the socket errors. Only when e.SocketError equals Success the chain continues. The SendRequest method creates the datagram and sends it over the channel:

   1: private void SendRequest()
   2: {
   3:     byte[] ntpData = new byte[48];
   4:     Array.Clear(ntpData, 0, ntpData.Length);
   5:     ntpData[0] = 0x1b;
   6:  
   7:     this.Args.SetBuffer(ntpData, 0, ntpData.Length);
   8:     this.Socket.SendAsync(this.Args);
   9: }

As you can see the 48 bytes array is cleared and the first byte is set to 0x1b then the entire buffer is assigned to the SocketAsyncEventArgs using the SetBuffer method. Finally it is passed to the SendAsync method so it is sent to the connected peer. The ReceiveResponse method instead, does not change the SocketAsyncEventArgs but simply calls the ReceiveAsyncMethod. The purpose of this method is not receiving bytes but putting the socket in receive mode so when a packet arrives it is received.

   1: private void ReceiveResponse()
   2: {
   3:     this.Socket.ReceiveAsync(this.Args);
   4: }

 

When the packet arrives, it is written inside the buffer prepared into the SocketAsyncEventArgs and I receive this data in the Operation_Completed method when LastOperation is Receive. This meand that between ReadAsync and Operation_Completed it may pass a long time depending on how fast is the answer from the server.

   1: private void ReadAndClose()
   2: {
   3:     byte[] ntpData = this.Args.Buffer;
   4:  
   5:     const byte offsetTransmitTime = 40;
   6:     ulong intpart = 0;
   7:     ulong fractpart = 0;
   8:  
   9:     for (int i = 0; i <= 3; i++)
  10:         intpart = 256 * intpart + ntpData[offsetTransmitTime + i];
  11:  
  12:     for (int i = 4; i <= 7; i++)
  13:         fractpart = 256 * fractpart + ntpData[offsetTransmitTime + i];
  14:  
  15:     ulong milliseconds = (intpart * 1000 + (fractpart * 1000) / 0x100000000L);
  16:  
  17:     TimeSpan timeSpan = TimeSpan.FromTicks((long)milliseconds * TimeSpan.TicksPerMillisecond);
  18:  
  19:     DateTime dateTime = new DateTime(1900, 1, 1);
  20:     dateTime += timeSpan;
  21:  
  22:     DateTime networkDateTime = dateTime.ToLocalTime();
  23:  
  24:     this.OnCompleted(networkDateTime);
  25:  
  26:     this.Socket.Shutdown(SocketShutdown.Both);
  27:     this.Socket.Close();
  28:     this.Socket = null;
  29: }

 

The ReadAndClose method receive the buffer and decode its content according with the NTP protocol specifications. Finally it calls ShutDown and Close to terminate the connection. After this the Socket instance is cleared because on the next request I have to create it again.

Using the NtpClient

Once the NtpClient class has been created it is time to use it in a Windows Phone application. Using this class is straightforward. You create the client instance and then call the GetNetworkTimeAsync every time you need to request the datetime. The class exposes two events Completed and Error that are raised accordin with the result of the request:

   1: public partial class MainPage : PhoneApplicationPage
   2: {
   3:     public NtpClient Client { get; set; }
   4:  
   5:     public MainPage()
   6:     {
   7:         InitializeComponent();
   8:  
   9:         this.Client = new NtpClient(new DnsEndPoint("0.pool.ntp.org", 123));
  10:         this.Client.Completed += new EventHandler<NtpQueryCompletedEventArgs>(Client_Completed);
  11:         this.Client.Error += new EventHandler<NtpQueryErrorEventArgs>(Client_Error);
  12:     }
  13:  
  14:     private void Button_Click(object sender, RoutedEventArgs e)
  15:     {
  16:         this.Client.GetNetworkTimeAsync();
  17:     }
  18:  
  19:     private void Client_Completed(object sender, NtpQueryCompletedEventArgs e)
  20:     {
  21:         this.Result.Text = e.Result.ToString(CultureInfo.CurrentCulture);
  22:     }
  23:  
  24:     private void Client_Error(object sender, NtpQueryErrorEventArgs e)
  25:     {
  26:         this.Result.Text = e.Error.ToString();
  27:     }
  28: }

 

The NtpClient class does not gracefully handles a double connection request but simply throw away the preceding destroying the socket before creating another one. This is for sure an improvement you can do by yourself.

The socket are a great opportunity for doing beautiful applications. An example of the power of sockets is my Silver VNC Client for Windows Phone that is available on marketplace The VNC client uses a TCP channel to connect to a VNC server and remotely view the desktop of a computer. I hope you enjoy the free edition.

Download the source code

 


Subscribe

Comments

  • MisterGoodcat

    Re: Windows Phone 7.5: Using sockets


    posted by MisterGoodcat on Jan 18, 2012 11:37

    Hi Andrea!

    An NTP client is a very nice sample to demonstrate sockets programming, and your article (as always) is written very well. 

    For those interested in more details on NTP, let me point out the recommended way to get the accurate time. The approach in the article to use the transmitted server time works for simple scenarios, but it does not take the transmission time into account (the time it takes for the NTP messages to be transferred over the network). For example, if the server is a large distance away from your current location, and/or if the network is slow, it may take up to seconds to receive the answer. Although the time server itself is really accurate in tracking the time (especially primary servers that directly sync with atomic clocks), this precision then is lost.

    To work around this issue, the messages send to and received from a time server contain several additional time stamps that are used to improve this situation a lot. The server records both the time when a client message arrives as well as the time when it sends out the response. The client on the other hand also tracks both the time it sends out the request, and the time when a response is received. With these four timestamps it's possible to get a very precise idea of _the offset_ the local clock on the client is running at, as (pseudo code):

    (ServerReceiveTimestamp - ClientSendTimestamp) - (ClientReceiveTimestamp - ServerSendTimestamp) / 2.0

    You can then correct the local time by adding the above offset to it (which of course might also be negative).

    If you're interested in a full implementation of (S)NTP according to RFC 5905 for Windows Phone 7, including a sample application that makes use of the above, you can take a look at my open source project "Phone Net Tools" here: http://phonenettools.codeplex.com/ - I've just checked in a minor fix for that very timestamp computation that was sitting on my hard disk for a while. The described way is very handy if you e.g. want to produce accurate timestamps on the phone to sync events between multiple devices or the device and desktop applications. In my experience, it's possible to achieve accuracy of the order of milliseconds with this.


  • vedanayagan

    Re: Windows Phone 7.5: Using sockets


    posted by vedanayagan on May 14, 2012 13:36

    How to Display the current time (hours, minutes, seconds). The display shall be updated (but not synchronized) each second.

     Using This Tine Servers

     * time1.ucla.edu

      * time.ien.it

      * time-nw.nist.gov

     

     

     

    Thanks in advance

    G.Vedanayagam

     

     

     

     

     

     

     

     

  • vedanayagan

    Re: Windows Phone 7.5: Using sockets


    posted by vedanayagan on May 14, 2012 13:37

    How to Display the current time (hours, minutes, seconds). The display shall be updated (but not synchronized) each second For WINDOWS PHONE 7

     Using This Tine Servers

     * time1.ucla.edu

      * time.ien.it

      * time-nw.nist.gov

     

     

     

    Thanks in advance

    G.Vedanaya

Add Comment

Login to comment:
  *      *       

From this series