Fading Coder

One Final Commit for the Last Sprint

Home > Notes > Content

Building a WebSocket Server with SuperSocket 2.0

Notes May 16 2

This implementation targets a development environment utilizing Windows 10, Visual Studio 2019, and .NET Core 3.1, relying on the SuperSocket.WebSocket.Server version 2.0.0-beta.8 library.

To instantiate a WebSocket server, the WebSocketHostBuilder class is employed. This builder allows for the configuration of message handlers, WebSocket parameters, and logging via a fluent API. When integrating custom command logic, it is necessary to transform the raw WebSocketPackage into a StringPackageInfo object. This transformation is handled by a custom mapper, such as the MessageStringMapper detailed below.

It is important to note that command classes must inherit from IAsyncCommand<WebSocketSession, StringPackageInfo>. Furthermore, the priority lies with the command registration; if UseCommand is utilized to register specific commands, the fallback handler defined in UseWebSocketMessageHandler will be bypassed.

MessageStringMapper Implementation

using System;
using System.Linq;
using SuperSocket.ProtoBase;
using SuperSocket.WebSocket;

namespace WebSocketServerExample.Core
{
    public class MessageStringMapper : IPackageMapper<WebSocketPackage, StringPackageInfo>
    {
        public StringPackageInfo Map(WebSocketPackage sourcePackage)
        {
            var packageInfo = new StringPackageInfo();
            
            if (string.IsNullOrEmpty(sourcePackage.Message))
            {
                return packageInfo;
            }

            var segments = sourcePackage.Message.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            
            packageInfo.Key = segments[0];
            
            // Use range operator to extract parameters efficiently
            packageInfo.Parameters = segments.Length > 1 ? segments[1..] : Array.Empty<string>();
            packageInfo.Body = segments.Length > 1 ? string.Join(" ", segments[1..]) : string.Empty;

            return packageInfo;
        }
    }
}

Server Configuration and Startup

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using SuperSocket.Command;
using SuperSocket.ProtoBase;
using SuperSocket.WebSocket.Server;
using WebSocketServerExample.Commands;

namespace WebSocketServerExample
{
    internal class ServerBootstrap
    {
        public static async Task Main()
        {
            var hostBuilder = WebSocketHostBuilder.Create()
                .ConfigureAppConfiguration((ctx, configBuilder) =>
                {
                    configBuilder.AddInMemoryCollection(new Dictionary<string, string>
                    {
                        {"serverOptions:name", "PrimaryWebSocketHost"},
                        {"serverOptions:listeners:0:ip", "Any"},
                        {"serverOptions:listeners:0:port", "8080"}
                    });
                })
                .ConfigureLogging((ctx, loggingBuilder) =>
                {
                    loggingBuilder.AddConsole();
                })
                .UseCommand<StringPackageInfo, MessageStringMapper>(commandConfig =>
                {
                    // Register specific command implementations
                    commandConfig.AddCommand<AddCommand>();
                    commandConfig.AddCommand<DivCommand>();
                    commandConfig.AddCommand<MulCommand>();
                    commandConfig.AddCommand<SubCommand>();
                    commandConfig.AddCommand<EchoCommand>();
                })
                // Fallback handler (ignored if UseCommand processes the message)
                .UseWebSocketMessageHandler(async (session, message) =>
                {
                    var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    var response = $"[{timestamp}] Server received: {message.Message}";
                    await session.SendAsync(response);
                })
                .Build();

            await hostBuilder.RunAsync();
        }
    }
}

Related Articles

Designing Alertmanager Templates for Prometheus Notifications

How to craft Alertmanager templates to format alert messages, improving clarity and presentation. Alertmanager uses Go’s text/template engine with additional helper functions. Alerting rules referenc...

Deploying a Maven Web Application to Tomcat 9 Using the Tomcat Manager

Tomcat 9 does not provide a dedicated Maven plugin. The Tomcat Manager interface, however, is backward-compatible, so the Tomcat 7 Maven Plugin can be used to deploy to Tomcat 9. This guide shows two...

Skipping Errors in MySQL Asynchronous Replication

When a replica halts because the SQL thread encounters an error, you can resume replication by skipping the problematic event(s). Two common approaches are available. Methods to Skip Errors 1) Skip a...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.