One of the features introduced with Silverlight 2 is socket-based network communications.   While there are a few differences between Silverlight Sockets and WPF ( or Win Form ) Sockets, the code is surprisingly portable between the frameworks.

In an effort to show-case both the power of Silverlight 2 Sockets and their similarity to the standard .Net 3.5 Sockets ( used by WPF, Win Forms, Consoles, etc. ), I’ve created an example chat system that can host a front-end written in Silverlight or WPF.  The backend can be run by any .Net 3.5 application framework, and I’ve included both a WPF version as well as a Console version.

Download the Solution Here

Chat System Components

The core of the system is found in the ‘Chat’ project.  The core classes are:

  • Client – Handles a client connection and logic ( consumable by Silverlight and WPF )
  • Server – Manages all client connections and logic
  • UserSocket – Wraps all socket communication asynchronously, and is used by both the client & server
  • Message – All activity between client(s) and the server is done through messages.  Message contains methods to construct byte packets, or ( given a byte stream ) create a Message.

Silverlight-Specific Components

Silverlight connections cannot be made to a server unless the server you’re connecting to provides a valid policy file.  The way Silverlight handles this is by making a request to port 943 with the text “<policy-file-request/>”.  You must respond to the request with a valid AccessPolicy XML file that explicitly declares what URI’s may access the port you’re trying to connect to, and on what port you will accept connections.

I have wrapped all the functionality needed to serve an access policy into the class ‘PolicyServer’.  This class will listen on port 943, and respond to policy requests with either the default embedded policy file, or with any byte[] array you pass in ( it will need to be an access policy file that allows the port you’re trying to connect to, otherwise Silverlight will not connect ).

One of the restrictions to the Socket system in Silverlight 2 is that connections must be made on ports between 4502-4532. In order for the client to connect, the server must be running within that range, and the access policy file must specify the port(s) allowed.  The embedded example access policy file allow connections to any of the ports in that range.

Silverlight-Specific Code

All core components in the system are shared between Silverlight & WPF ( All files in the ChatSL project are linked to their counterparts in the Chat project ).  While almost all of the code is identical, there are two different sections of code that need to be different between clients.  I’m able to keep all the code in the same file by using # directives to check which library is being compiled.

The first directive conditional is in the creation of the EndPoint in the Client class:

#if SILVERLIGHT
endPoint = new DnsEndPoint(_host, _port);
#else
IPHostEntry hostEntry = Dns.GetHostEntry(_host);

IPAddress address = (from a in hostEntry.AddressList
where a.AddressFamily == AddressFamily.InterNetwork
select a).First();
endPoint = new IPEndPoint(address, _port);
#endif
 
For the Silverlight piece of this code, the Silverlight-only DnsEndPoint class is used to build the correct endpoint.  The non-Silverlight code does have the DnsEndPoint class, and we need to do a bit of work to retrieve a valid address for the host.  You might be tempted to just use code similar to the following:
 
endPoint = new IPEndPoint(IPAddress.Any, _port);

However on my machine, this pulls back the IPV6 protocol for the endpoint, which won’t work with our socket ( which we specify as IPV4 ).  To handle the issue, I query the address list for the correct protocol and select the first match.
 
Included Projects

The included solution contains 7 projects:

  • Chat – Contains the core classes of the chat system
  • ChatSL – Silverlight library that LINKS to the files in the Chat project.
  • ConsoleServer – Runs the Chat server in a console
  • SilverlightUI – Runs the client as a Silverlight Application
  • SilverlightUI.Web – Host the Silverlight Client Application
  • WPFServer – Runs the Chat server as a WPF application
  • WPFUI – Runs the client as a WPF Application

I’m contemplating adding this solution to Code Project, and to periodically make updates to the Server & Client to support new functionality.  If you have any questions with the code, or if you’d like to see new features added, leave a comment or feel free to email me at colinw@codesprouts.com

- Colin