Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Web Socket Server

4.76/5 (35 votes)
3 Jun 2010CPOL5 min read 600.3K   38.3K  
An example of an implementation of a web socket server and how to interact with it from JavaScript

N.B.: At the point when a wrote this article the standard was still being worked out. A lot have changed, and you will need to tweak the code provided, to get it to work.

Introduction

I've been hearing about HTML5 for quite some time now, and I especially liked the idea of web sockets. Giving us the ability to send data directly to the user, instead of doing something like polling with AJAX requests seems like a very neat idea.

So the other day, I decided that I would try to make a small server and test it out on my localhost. As far as I can tell, only Google Chrome supports web sockets at the moment, but I sure hope that it will pick up.

This screenshot is an example of how web sockets could be used (the code is in the attached zip file).

c_sharp_web_socket_server/WebSocketServer.png

Naturally, I started the development with a Google search; this however didn't really help much. I found a Python and a PHP implementation, but not much about C#. This is my motivation for writing this article; I'll walk though some of the code for the server and a bit about how to interact with it from JavaScript.

Background

The server is heavily based on sockets. I don't think you would need to be very experienced in working with sockets, but a bit of knowledge shouldn't hurt. The code is not entirely simple, I'm using a small amount of delegates and lambda expressions, but again, it’s not very hard either. I guess you'll be fine.

Using the Code

The code is organized into a couple of classes in a class library, which could be included as a project in your solution or compiled into an assembly. It’s hard to create a ready-made demo application as you need a webserver, a browser and the web socket server to run simultaneously in order for it to work. But I'll try to explain how to get it all working. The project contains two main classes: WebSocketServer and WebSocketConnection. The WebSocketServer is responsible for handling all the client connections and the initial handshaking. The WebSocketConnection handles the individual connections. The server listens for connections and creates the connection objects upon connection, and the connection objects are used to interact with the clients (sending/receiving data).

The following is an example of how you could start the server:

C#
var wss = new WebSocketServer(8181, 
                              "http://localhost:8080",
                              "ws://localhost:8181/service");
wss.Start();

The constructor takes three arguments:

C#
public WebSocketServer(int port, string origin, string location)
  • The port on which to listen for connections
  • The origin of the connections (the location of the web page)
  • The location of the server.

The last two arguments are used when "authenticating" the connections through the handshake between the server and the client. The inner workings of the protocol is described here: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75

To enable you to see what is happening in the server, a very crude logging mechanism is implemented: You can attach a TextWriter to the server, and specify the logging level with the ServerLogLevel enum:

C#
wss.Logger = Console.Out;
wss.LogLevel =ServerLogLevel.Verbose;

There are three different log levels:

C#
ServerLogLevel.Verbose //tells you just about everything 
                       //(including all the data received)
ServerLogLevel.Subtle  //tells you when clients connect/disconnect 
                       //and when they are sending data to the server 
ServerLogLevel.Nothing //well.. nothing.

An even better way keep an eye on what is going on, is to attach methods to the events that the server and the connections are invoking:

C#
wss.ClientConnected += new ClientConnectedEventHandler(OnClientConnected);
 
///
 
static void OnClientConnected(WebSocketConnection sender, EventArgs e)
{
  Console.WriteLine("client connected");
  sender.Disconnected += new WebSocketDisconnectedEventHandler(OnDisconnected);
  sender.DataReceived += new DataReceivedEventHandler(OnDataReceived);
}
 
static void OnDataReceived(WebSocketConnection sender, DataReceivedEventArgs e)
{
  Console.WriteLine("data received");
}
 
static void OnDisconnected(WebSocketConnection sender, EventArgs e)
{
  Console.WriteLine("client disconnected");
}

The "sender" in these methods is always the WebSocketConnection object associated with the connection. The only method that has data in the EventArgs is the OnDataReceived method, the EventArgs (DataReceivedEventArgs) in this method contains the size of the data and the data itself, these are accessible through properties on the object (Size and Data). The data transferred between the client and the server is UFT8 encoded strings (as specified in the protocol).

The above is pretty much the simplest usage example of the classes, but in order to get any clients to connect we need some JavaScript and a browser to run it. But before we continue to the JavaScript, I'd like to just attach a few extra words to the classes:

As I said, the WebSocketSever object listens for new clients and creates the WebSocketConnection objects as new clients connect. The objects are kept in a List, and this list is updated as the clients disconnect. The listener socket is accessible though the ListenerSocket property, and the List though the Connections property. Apart from the Start method, the server contains two public methods; SendToAll and SendToAllExceptOne. These methods can be used to send data to all the connected clients, and to send data to all the connected clients except a specified client (this could be used in a scenario where a client wishes to send data to everybody else). These methods simply call the public Send method on the WebSocketConnection objects in the List. This method sends a string to the client. The WebSocketConnection has one more public function: Close, this method just closes the connecting socket. The socket is available thought the ConnectionSocket property.

The following is an outline of the public methods, properties and events of the two classes:

WebSocketServer:

C#
// an event that is triggered every time a client connects to the server
event ClientConnectedEventHandler ClientConnected;
// a property to access the list of WebSocketConnections of the server
List<WebSocketConnection> Connections;
// a property to access the socket that is listening for new connections
Socket ListenerSocket; 
// a property that can be used to achieve simple logging
TextWriter Logger; 
// a property that determines the level of verbose-ness of the logging
ServerLogLevel LogLevel; 
// a property to access the port the sever is listening to
int Port; 
// sends a string to all connected clients
void SendToAll(string str); 
// sends a string to all connected clients except a specified client
void SendToAllExceptOne(string str, WebSocketConnection indifferent);
// starts the server
void Start(); 

WebSocketConnection:

C#
// method that closes the connecting socket
void Close(); 
// property to access the connecting socket
Socket ConnectionSocket; 
// event that is triggered whenever data is received
event DataReceivedEventHandler DataReceived;
// event that is triggered when the client disconnects
event WebSocketDisconnectedEventHandler Disconnected; 
// a property to get a Guid for the client connection
Guid GUID; 
// method that sends a string to the client
void Send(); 

So! After all that it is time to look at the JavaScript. A very simple client would look a bit like this:

I use JQuery and put the code below inside the $(document).ready() function, but I guess you could do it in a lot of ways.

JavaScript
if('WebSocket' in window){
  connect('ws://localhost:8181/service');
}
 
function connect(host) {
  var ws = new WebSocket(host);
  ws.onopen = function () {
    alert('connected');
  };
 
  ws.onmessage = function (evt) {  
    alert('reveived data:'+evt.data);
  };
 
  ws.onclose = function () {
    alert('socket closed');
  };
};

Source Code

The attached source code contains the WebSocketServer class library along with two other projects: ChatClient and WebSocketChatServer. I've included the two other projects to give you a feel of how the code works. Just "start" the solution, and open a few browser windows on localhost:8080, and you should be able to chat with yourself.

Points of Interest

One thing to take notice of is the web socket server location. Even though you are just running the server on your localhost, you will need to specify an address i.e. "ws://localhost:8181" does NOT work, but "ws://localhost:8181/something" does. But as long as you just use the same address in the JavaScript and the C# server code, you should be fine.

To get a better idea of what web sockets are, and what they can do, take a look at these links:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)