当前位置: 首页 > news >正文

SuperSocket 动态协议服务端开发全解析

SuperSocket:动态协议服务端开发全解析

在开发 TCP/Socket 服务时,我们经常会遇到 不同协议类型共存 的需求,例如一部分客户端用 分隔符协议(Terminator),另一部分客户端用 固定长度头协议(FixedHeader)。本文通过 WPF 框架结合 SuperSocket,详细讲解如何实现一个灵活可配置的服务端。


1. SuperSocket 简介

SuperSocket 是一款基于 .NET 的高性能、可扩展 TCP Socket 框架。
它的核心特点包括:

  • 高性能 I/O:基于 System.IO.Pipelines,支持异步流处理。
  • 协议可扩展:通过 PipelineFilter 可以定义各种自定义协议。
  • DI 与 Logging 支持:完美集成 .NET Core 的依赖注入与日志体系。
  • 支持多种主机类型:可在 Console、Windows 服务、WPF 或 ASP.NET 环境中运行。

在 SuperSocket 中,核心概念有:

  1. TPackageInfo:代表每个完整消息包的对象,框架通过 PipelineFilter 将字节流解码成 TPackageInfo
  2. PipelineFilter:字节流到消息包的解码器,支持多种协议类型(Terminator、FixedHeader、LengthField 等)。
  3. IPipelineFilterFactory:工厂接口,用于创建不同类型的 PipelineFilter。
  4. AppSession:每个客户端连接的会话对象,通过它发送或接收消息。

2. 定义消息包

在本例中,我们定义一个简单的 StringPackageInfo

public class StringPackageInfo
{public string Key { get; set; }public string[] Parameters { get; set; } = Array.Empty<string>();public string Body { get; set; }
}
  • Key:命令名,例如 ADD
  • Parameters:命令参数,例如 "1 2"
  • Body:原始消息文本。

3. 自定义 PipelineFilter

3.1 Terminator 协议

public class MyTerminatorFilter : TerminatorPipelineFilter<StringPackageInfo>
{public MyTerminatorFilter(byte[] terminator) : base(terminator) { }protected override StringPackageInfo DecodePackage(ref ReadOnlySequence<byte> buffer){var text = buffer.GetString(Encoding.UTF8)?.Trim();if (string.IsNullOrEmpty(text)) return new StringPackageInfo();var parts = text.Split(' ', StringSplitOptions.RemoveEmptyEntries);return new StringPackageInfo{Key = parts[0],Parameters = parts.Skip(1).ToArray(),Body = text};}
}
  • 通过 TerminatorPipelineFilter,我们可以指定任意分隔符(如 \r\n$$ 等)。
  • DecodePackage 将字节流解码成 StringPackageInfo

3.2 FixedHeader 协议

using SuperSocket.ProtoBase;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace TcpSvrTest.Filter;public class MyFixedFilter : FixedHeaderPipelineFilter<StringPackageInfo>
{//数据格式://  -------+----------+-------------------------------------------+//  0001   | 00000010 |  4C36 3150 2D43 4D2B 4C30 3643 5055 2D43 4D2B 4C4A   |//  固定头 | 数据长度 |  数据                                                |//  2byte  |  4byte   |                                                      |//  -------+----------+---------------------------------+private const int HeaderSize = 6; //Header总长度public MyFixedFilter(): base(HeaderSize){}string cmdValue = "";protected override int GetBodyLengthFromHeader(ref ReadOnlySequence<byte> buffer){var reader = new SequenceReader<byte>(buffer);// ✅ 1. 检查是否有足够的头部数据if (buffer.Length < 6){// 数据不足,等待更多数据到来(返回 -1)return -1;//这会将客户端被踢掉}//先读头reader.TryReadLittleEndian(out short fix);if (!Enum.IsDefined(typeof(CommandId), (UInt16)fix)){//Console.WriteLine("不是有效的固定头");return -1;//这会将客户端被踢掉}//头转换为枚举字符串,变成Key,这样就可以路由了cmdValue = ((CommandId)fix).ToString(); ;//他真的,我哭死(太贴心了)reader.TryReadLittleEndian(out int len); //以小端方式读取short类型数据return len;}protected override StringPackageInfo DecodePackage(ref ReadOnlySequence<byte> buffer){StringPackageInfo info = new StringPackageInfo();// ✅ 3. 枚举变Keystring key = cmdValue; // 直接得到 "LOGIN", "SEND"...//跳过前面6个字节var new_buffer = buffer.Slice(HeaderSize).ToArray();//合成数据info.Key = key; // 基于StringPackageInfo的Key可以实现路由~~~~~,这样固定头也可以路由,就可以有意义了info.Body = Encoding.UTF8.GetString(new_buffer);return info;}
}
  • FixedHeader 协议通过读取固定长度头部来获取消息体长度。
  • 非常适合二进制协议或者自定义长度包。

4. 配置工厂实现动态协议

为了支持 不同类型客户端协议动态选择,我们实现了 ConfigurableFilterFactory

public class ConfigurableFilterFactory : IPipelineFilterFactory<StringPackageInfo>
{private readonly string _protocolType;private readonly string _terminator;public ConfigurableFilterFactory(string protocolType, string terminator = "\r\n"){_protocolType = protocolType;_terminator = terminator;}public IPipelineFilter<StringPackageInfo> Create(object client){return _protocolType switch{"Terminator" => new MyTerminatorFilter(Encoding.UTF8.GetBytes(_terminator)),"FixedHeader" => new MyFixedFilter(),_ => throw new NotSupportedException($"Unknown protocol: {_protocolType}")};}
}
  • 通过依赖注入,我们可以在 WPF 或 Console 应用中选择协议类型。
  • Terminator 的结束符也可以动态配置。

5. 构建并启动 SuperSocket 服务

在 WPF 的异步方法中:

async Task StartTcp(string protocolType, string terminator)
{host = SuperSocketHostBuilder.Create<StringPackageInfo, CommandLinePipelineFilter>() // 占位 Filter.ConfigureServices((ctx, services) =>{services.AddSingleton<ConfigurableFilterFactory>(_ => new ConfigurableFilterFactory(protocolType, terminator));services.AddSingleton<IPipelineFilterFactory<StringPackageInfo>>(sp => sp.GetRequiredService<ConfigurableFilterFactory>());}).UsePipelineFilterFactory<ConfigurableFilterFactory>() // 泛型传类型.UsePackageHandler(async (session, package) =>{// 简单示例:返回命令结果await session.SendAsync(Encoding.UTF8.GetBytes($"Received: {package.Body}\r\n"));}).ConfigureSuperSocket(options =>{options.Name = "MyTcpServer";options.Listeners = new List<ListenOptions>{new ListenOptions { Ip = "0.0.0.0", Port = 8051 }};}).ConfigureLogging((ctx, logging) =>{logging.AddConsole();logging.AddDebug();}).Build();await host.StartAsync(); // WPF UI 线程安全
}

注意点

  1. 不要用 RunAsync(),因为它会阻塞线程。WPF 里用 StartAsync() 更安全。
  2. 停止服务
await host.StopAsync();
host = null;

6. 超级实用技巧

  1. 动态协议切换

    • 使用 IPipelineFilterFactory + DI,可以在外部配置文件里控制协议类型和结束符,无需修改代码。
  2. 日志和调试

    • SuperSocket 内置对 Microsoft.Extensions.Logging 支持,方便在开发和生产环境打印调试信息。
  3. 大包支持

    • MaxPackageLength 可以设置为 1GB 或更多,支持大数据传输。
  4. 命令行或 WPF 混合使用

    • SuperSocket 既可以在 Console,也可以在 WPF 窗口中运行。
    • 异步模式保证 UI 不被阻塞。

7. 配置文件示例(appsettings.json)

{"Protocol": {"Type": "Terminator","Terminator": "$$"},"Server": {"Port": 8051}
}
  • WPF 启动时读取配置文件即可动态选择协议和结束符。
  • 支持快速切换到 FixedHeader 协议。

8. 总结

通过本文方法,你可以:

  1. 灵活支持多种协议类型(Terminator / FixedHeader)。
  2. 动态配置结束符,无需修改代码。
  3. 集成到 WPF 或其他 .NET 应用中。
  4. 利用 SuperSocket DI 与 Logging 做可扩展、可维护的高性能服务端。

SuperSocket 结合 DI + Factory 模式,是实现可扩展 TCP 服务的最佳实践。


文章转载自:

http://42m9wpGs.hncrc.cn
http://70cBd0mi.hncrc.cn
http://d0qMImYb.hncrc.cn
http://FeepwkOE.hncrc.cn
http://oB8JENuU.hncrc.cn
http://N6R7FEM2.hncrc.cn
http://xKyh24R1.hncrc.cn
http://FVRZcTvj.hncrc.cn
http://51koVcAT.hncrc.cn
http://W09BlqPe.hncrc.cn
http://OozKPlum.hncrc.cn
http://OvGbr47P.hncrc.cn
http://zMpMlqhv.hncrc.cn
http://fTiksJUU.hncrc.cn
http://B4N2Lgxh.hncrc.cn
http://rtlZoWGq.hncrc.cn
http://dhlA7gU9.hncrc.cn
http://PIblDcep.hncrc.cn
http://552qrTcK.hncrc.cn
http://OHvA7yXA.hncrc.cn
http://mfc1GZp6.hncrc.cn
http://oHm4AZ3G.hncrc.cn
http://nIAeQBwy.hncrc.cn
http://QHvX2EuM.hncrc.cn
http://kTyb1Kyn.hncrc.cn
http://aef8RSCj.hncrc.cn
http://9qGRH9SF.hncrc.cn
http://zrxQZ0WS.hncrc.cn
http://t5LYGNeb.hncrc.cn
http://pbF9uwHI.hncrc.cn
http://www.dtcms.com/a/366115.html

相关文章:

  • RTSP 协议认证机制详解:Basic 与 Digest 的原理与应用
  • 小迪安全v2023学习笔记(七十七讲)—— 业务设计篇隐私合规检测重定向漏洞资源拒绝服务
  • 【RNN-LSTM-GRU】第四篇 GRU门控循环单元:LSTM的高效替代者与实战指南
  • 为何三折叠手机只有华为可以?看华为Mate XTs非凡大师就知道
  • 2025年09月03日最热门的开源项目(Github)
  • Redis底层实现原理之五大基础结构
  • 云手机与网络游戏相结合的优势?
  • Docker学习笔记(二):镜像与容器管理
  • 20. 云计算-华为云-云服务
  • 域名注册后,为什么还需要域名解析?
  • 嵌入式硬件 - 51单片机3
  • 操作系统(二) :进程与线程
  • 力扣14:最长公共前缀
  • 【面试题】生成式搜索能否保证top-1的准确性?
  • C++类和对象(上):从设计图到摩天大楼的构建艺术
  • 从战略亏损到万亿估值:新“股王”寒武纪如何改写中国芯片叙事?
  • Sentinel 与 Feign 整合详解:实现服务调用的流量防护
  • solar应急响应-7月
  • 遥感语义分割辅导
  • 基于Hadoop的网约车公司数据分析系统设计(代码+数据库+LW)
  • 【序列晋升】28 云原生时代的消息驱动架构 Spring Cloud Stream的未来可能性
  • Vue3+TS 交互式三层关系图
  • HDFS机架感知、副本存放机制详解(附源码地址)
  • Deathnote: 1靶场渗透
  • 2025企业ODI备案全指南:五大出海场景解析与合规路径,中国卖家如何破局全球市场?
  • 飞算JavaAI开发在线图书借阅平台全记录:从0到1的实践指南
  • 用Logseq与cpolar:构建开源笔记的分布式协作系统
  • 【文件快速搜索神器Everything】实用工具强推——文件快速搜索神器Everything详细图文下载安装教程 办公学习必备软件
  • git命令常用指南
  • Java 和 Python 的执行方式有很大不同——Android学习