C# WebSocketServer服务器源代码

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# WebSocketServer服务器源代码

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:

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

The constructor takes three arguments:

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 rude logging mechanism is implemented: You can attach a TextWriter to the server, and specify the logging level with the ServerLogLevel enum:

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

There are three different log levels:

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:

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 wo