Daily Archives: April 10, 2008

Pushing Data to a Silverlight Client with Sockets: Part IDan Wahlin’s WebLog

Silverlight 2 has built-in support for sockets which creates some interesting possibilities.  If you've ever worked on a client-side application that needed to receive up-to-date data then you're probably used to solving the problem by polling.  With polling the client contacts the server on a consistent, timed basis to see if any updates are available.  ASP.NET AJAX provides a Timer control that makes this process easy and straightforward.

The problem with polling is that unless the data is changing a lot, most of the client checks to the server are simply wasted bandwidth in cases where no changes have occurred.  If you're calling a Web Service and passing JSON messages back and forth then the overhead is certainly minimal, but wouldn't it be nice if the server could push updates to the client as needed instead?  In fact, wouldn't it be nice if multiple clients could receive the same updates on a consistent basis so everyone is in sync?

What are Sockets?

Sockets allow a listener server to listen for clients that would like to connect to a specific socket (an IP address combined with a port).  As the clients connect the server can send data to them anytime and the clients can send data to the server as well.  Data flows both directions which allows the server to push data if desired.  The .NET framework provides direct support for using sockets through the System.Net.Sockets namespace and provides classes such as Socket and TcpListener that can be used to create a server application.  The following image shows a Silverlight 2 application built around the concept of sockets that allows a server application to push data down to a client that displays the score of a basketball game (click the image to view an animated gif that shows the application in progress):

 

The game is simulated on the server and as each team scores the update is pushed to the client so that the score and action that occurred can be displayed. 

Creating the Server

To create a server that uses sockets you’ll need to import the System.Net and System.Net.Sockets namespace.  You can use the Socket or TcpListener class to listen for client connection attempts but I opted for the TcpListener class since my Silverlight 2 clients would only be connecting over TCP anyway (as opposed to UDP or another protocol). The server application shown next listens on port 4530 which is in the range Silverlight 2 allows. 

Here's the code that starts up the TcpListener class as well as a timer that is used to send data to the client on a random basis.  The _TcpClientConnected object is a ManualResetEvent object that blocks threads until previous ones have connected.  The key line of code is the BeginAcceptTcpClient() method which asynchronously routes client connection attempts to a callback method named OnBeginAccept().

public void StartSocketServer() {     InitializeData();     _Timer = new System.Timers.Timer();     _Timer.Enabled = false;     _Timer.Interval = 2000D;     _Timer.Elapsed += new ElapsedEventHandler(_Timer_Elapsed);          try     {         //Allowed port range 4502-4532         _Listener = new TcpListener(IPAddress.Any, 4530);         _Listener.Start();         Console.WriteLine("Server listening...");         while (true)         {             _TcpClientConnected.Reset();             Console.WriteLine("Waiting for client connection...");             _Listener.BeginAcceptTcpClient(new AsyncCallback(OnBeginAccept),null);             _TcpClientConnected.WaitOne(); //Block until client connects         }     }     catch (Exception exp)     {         LogError(exp);     }        }

Once a client tries to connect the OnBeginAccept() method is called which sends team data down to the server and starts the timer which fakes the scores and game actions.  The stream used to write to each client is added to a collection since it's used later as changes on the server occur.  

private void OnBeginAccept(IAsyncResult ar) {     _TcpClientConnected.Set(); //Allow waiting thread to proceed     TcpListener listener = _Listener;     TcpClient client = listener.EndAcceptTcpClient(ar);     if (client.Connected)     {         Console.WriteLine("Client connected...");         StreamWriter writer = new StreamWriter(client.GetStream());         writer.AutoFlush = true;         _ClientStreams.Add(writer);         Console.WriteLine("Sending initial team data...");         writer.WriteLine(GetTeamData());         if (_Timer.Enabled == false)         {             _Timer.Start();         }     } }


The initial team data that is sent from the server to the client immediately after a client connects is created in the GetTeamData() method:

private string GetTeamData() {     StringWriter sw = new StringWriter();     using (XmlWriter writer = XmlWriter.Create(sw))     {         writer.WriteStartElement("Teams");         foreach (string key in _Teams.Keys)         {             writer.WriteStartElement("Team");             writer.WriteAttributeString("Name", key);             Dictionary<Guid, string> players = _Teams[key];             foreach (Guid playerKey in players.Keys)             {                 writer.WriteStartElement("Player");                 writer.WriteAttributeString("ID", playerKey.ToString());                 writer.WriteAttributeString("Name", players[playerKey]);                 writer.WriteEndElement();             }             writer.WriteEndElement();         }         writer.WriteEndElement();     }     return sw.ToString(); }

As the Timer object fires the _Timer_Elapsed() method is called which handles sending score updates to the client on a random basis to simulate plays in a game:

private void _Timer_Elapsed(object sender, ElapsedEventArgs e) {     SendData(GetScoreData());     //Setting new interval to simulate different data feed times     Random r = new Random();     _Timer.Interval = (double)r.Next(3000, 7000); }  private void SendData(string data) {     if (_ClientStreams != null)     {         foreach (StreamWriter writer in _ClientStreams)         {             if (writer != null)             {                 writer.Write(data);             }         }     } }

There’s quite a bit more code for the server application which you can download here.  The code shown above is really all that's involved for creating a server that listens for clients on a specific IP address and port.  In the next post on this topic I'll cover the client-side and discuss how Silverlight can connect to a server using sockets.

Silverlight 2 Networking OptionsDan Wahlin’s WebLog

image I've been spending my nights working on a new book covering Silverlight 2 and have been focusing on the new networking features that are available in the System.Net and related namespaces.  Silverlight's great at animating objects, performing transformations and collecting data with all of the new controls that are available, but at some point you'll need to retrieve data or send data to a service.  There's great support built-in for calling WCF services, ASMX services as well as other services.  Support for  calling REST APIs is also very good and easy to implement using classes such as WebClient and HttpWebRequest/HttpWebResponse.  Asynchronous requests can be issued and handled quite easily once you figure out the pattern (which is quite consistent throughout the different networking classes).

Serialization and Deserialization Options

Once data returns from a service you can parse it using multiple techniques.  I'll blog about these individually over the next few months but in a nutshell you can map XML data into CLR objects in Silverlight 2 using the XmlReader class, XmlSerializer class or the LINQ to XML technology and related classes such as XDocument.  JSON can be mapped to CLR objects using the DataContractJsonSerializer and other open source options are available at www.codeplex.com.  RSS and ATOM feeds can be parsed and items/entries can be accessed using classes such as SyndicationFeed and SyndicationItem.  All of this functionality is straightforward to use especially if you have a background in VB.NET or C#.  The  available networking and parsing classes make working with data (especially XML data) a pleasant experience.

Support for Sockets

In addition to the request/response features built into Silverlight 2 you can also use sockets to communicate and exchange data.  A socket is basically a port and an IP address used to send data between a client and a server.  Currently Silverlight 2 supports port ranges between 4502 and 4532 although it's possible that may change since it's still in the beta 1 stage.  By using sockets a Silverlight client can talk directly with a server that listens for client connections and the server can push data to the client without requiring the client to consistently poll the server for changes…that's cool!  If you've seen some of the sports scoring applications at ESPN.com then you've experienced some of the push technologies that are out there. 

I wanted to play around with the new sockets capabilities so I decided to build a sample application that could push simulated basketball game scores down to a client.  Multiple clients can connect to a socket server and the server can then push the same data out to the clients which is kind of interesting since they stay in sync.  I'm not going to go into details on the implementation of the server or Silverlight client in this post (those attending DevConnections Orlando will get some of this in my Silverlight 2 talk), but I'll be breaking down the different pieces in posts coming in the near future. 

Until then, here's what the application looks like at this point.  Score data is sent as XML from the server to the client along with details about what action occurred in the game.  The game data is randomly generated on the server to simulate turnovers, fouls, 2 point shots, 3 point shots and foul shots.  There's a lot more than can be done to enhance the application, but here's what it looks like to this point. 

SilverlightSockets

I'll be posting details about how to build a server and client that communicate via sockets soon.  In the meantime make sure you check out Tim Heuer’s blog on Silverlight 2 topics.  He's a Silverlight Evangelist for Microsoft (and good buddy) and has some awesome posts on Silverlight.  He posts about things that I haven't seen anywhere else.

If you’re brand new to Silverlight and not quite ready to get into something like networking features and sockets, check out the following videos I put together that walk through Scott Guthrie’s great written tutorials:

Part 1: Creating "Hello World" with Silverlight 2 and VS 2008
Tutorial
Video Tutorial

Part 2: Using Layout Management
Tutorial
Video Tutorial

Part 3: Using Networking to Retrieve Data and Populate a DataGrid
Tutorial
Video Tutorial

Part 4: Using Style Elements to Better Encapsulate Look and Feel
Tutorial
Video Tutorial

Part 5: Using the ListBox and DataBinding to Display List Data
Tutorial
Video Tutorial

Part 6: Using User Controls to Implement Master/Details Scenarios
Tutorial
Video Tutorial

Part 7: Using Templates to Customize Control Look and Feel
Tutorial
Video Tutorial

Part 8: Creating a Digg Desktop Version of our Application using WPF
Tutorial
Video Tutorial

WP Like Button Plugin by Free WordPress Templates