Skip to content

WebSocketListener Echo Server Example

vtortola edited this page Sep 3, 2014 · 1 revision

This is a very simple example of a WebSocket server that just echoes whatever input it gets.

Installing

WebSocketListener is available through NuGet

PM> Install-Package vtortola.WebSocketListener

Setting the service up

To start the server is needed to select an endpoint and optionally add custom configuration and extensions. In this case, a simple WebSocket at port 8005 will do:

static void Main(string[] args)
{
    CancellationTokenSource cancellation = new CancellationTokenSource();
    
    var endpoint = new IPEndPoint(IPAddress.Any, 8005);
    WebSocketListener server = new WebSocketListener(endpoint);
    var rfc6455 = new vtortola.WebSockets.Rfc6455.WebSocketFactoryRfc6455(server);
    server.Standards.RegisterStandard(rfc6455);
    server.Start();

    Log("Echo Server started at " + endpoint.ToString());

    var task = Task.Run(() => AcceptWebSocketClientsAsync(server, cancellation.Token));

    Console.ReadKey(true);
    Log("Server stoping");
    cancellation.Cancel();
    task.Wait();
    Console.ReadKey(true);
}

AcceptWebSocketClientsAsync is an asynchronous method but it is not being awaited, it is executed in the background. We keep the reference to the task to wait for the listener to stop accepting before shutdown the process.

Processing client requests

Accepting clients must happen inside a loop and wrapped in a try\catch to ensure that clients are accepted continuously:

static async Task AcceptWebSocketClientsAsync(WebSocketListener server, CancellationToken token)
{
    while (!token.IsCancellationRequested)
    {
        try
        {
            var ws = await server.AcceptWebSocketAsync(token).ConfigureAwait(false);
            if (ws != null)
                Task.Run(()=>HandleConnectionAsync(ws, token));
        }
        catch(Exception aex)
        {
            Log("Error Accepting clients: " + aex.GetBaseException().Message);
        }
    }
    Log("Server Stop accepting clients");
}

AcceptWebSocketAsync can yield a null object if the server is closing down. HandleConnectionAsync is an asynchronous method that is not awaited. It handles the incoming client in a background thread and allows AcceptWebSocketAsync to quickly await more clients.

Processing input

In this specific case, the server reacts to the incoming input and yields an output.

static async Task HandleConnectionAsync(WebSocket ws, CancellationToken cancellation)
{
    try
    {
        while (ws.IsConnected && !cancellation.IsCancellationRequested)
        {
             String msg = await ws.ReadStringAsync(cancellation).ConfigureAwait(false);
             if(msg != null)
                 ws.WriteString(msg);
        }
    }
    catch (Exception aex)
    {
        Log("Error Handling connection: " + aex.GetBaseException().Message);
        try { ws.Close(); }
        catch { }
    }
    finally
    {
       ws.Dispose();
    }
}

This method just:

  • awaits a new incoming message.
  • checks if it is a text or binary message.
  • sends it back.

Other examples:

You may like to take a look on the Rx Chat Server sample, a chat server implemented with WebSocketListener and the Reactive Extensions:

Also, you may like to take a look on the Terminal Server sample