-
Notifications
You must be signed in to change notification settings - Fork 85
WebSocketListener Echo Server Example
This is a very simple example of a WebSocket server that just echoes whatever input it gets.
WebSocketListener is available through NuGet
PM> Install-Package vtortola.WebSocketListener
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.
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.
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.
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