due是一款基于Go语言开发的轻量级、高性能分布式游戏服务器框架。 其中,模块设计方面借鉴了kratos的模块设计思路,旨在为游戏服务器开发提供完善、高效、标准化的解决方案。 框架自创建至今已在多个企业级游戏项目中上线实践过,稳定性有充分的保障。
本项目是 due 游戏框架的 C# 客户端,方便开发者使用 C# 对接 due 网关进行游戏开发与联调。
- 💡 简单性:架构简单,源码简洁易理解。
- 🚠 便捷性:仅暴露必要的调用接口,减轻开发者的心智负担。
- 🚀 高性能:与 due 框架原生二进制协议完全一致,传输零冗余。
✈️ 多协议:同时提供 tcp、ws 两种传输实现,可按需自由切换。- 🎟️ 扩展性:网络层(INetwork)、编解码器(IEncoding)均为接口设计,方便扩展自有实现。
- ⚖️ 稳定性:协议与 due 官方网关严格对齐,已在真实业务中联调验证。
- 网关:支持 tcp、ws 两种协议的客户端接入。
- 协议:支持 json 编解码,可扩展自定义编解码器。
- 心跳:内置心跳保活,支持接收服务器心跳附带的服务器时间。
- 网络:网络层接口化设计(INetwork),内置 tcp(Tcp)与 ws(Ws)两种实现。
- 打包:打包器(Packer)支持自定义字节序、路由字节数、序列号字节数、消息体上限。
- 安全:支持 due 会话安全(security),握手协商会话密钥并对业务消息加解密。
通过 dotnet CLI 引入本项目源码编译使用:
$ dotnet build
using Due; // 创建打包器 Packer packer = new Packer(); // 创建客户端:TCP 传输 // Client client = new Client(new Due.Network.Tcp(packer), packer); // 创建客户端:WebSocket 传输 Client client = new Client(new Due.Network.Ws(packer), packer); // 监听连接 client.OnConnect((c) => { Console.WriteLine("connect success"); // 在独立线程中周期发送消息 new Thread(() => { while (true) { // 发送消息(route=1, seq=1) c.Send(1, 1, new { message = "hello server" }); Thread.Sleep(1000); } }).Start(); }); // 监听连接断开 client.OnDisconnect((c) => { Console.WriteLine("disconnect"); // 重新连接 c.Connect("ws://127.0.0.1:3553"); }); // 监听接收到消息 client.OnReceive((c, message) => { Console.WriteLine($"receive message; route: {message.Route}, seq: {message.Seq}, data: {message.Data?.GetString()}"); }); // 监听服务器心跳附带的服务器时间 client.OnHeartbeat((c, millisecond) => { if (millisecond != null) { Console.WriteLine($"server heartbeat timestamp: {millisecond}ms"); } }); // 建立连接 client.Connect("ws://127.0.0.1:3553");
打包器(Packer)用于消息的打包与解包,可通过构造函数自定义协议参数:
// 字节序、路由字节数、序列号字节数、编解码器 Packer packer = new Packer( byteOrder: ByteOrder.BigEndian, // 字节序,默认为 BigEndian routeBytes: 2, // 路由字节数,可选 1 | 2 | 4,默认为 2 seqBytes: 2, // 序列号字节数,可选 0 | 1 | 2 | 4,默认为 2 encoding: new Json() // 编解码器,默认为 Json );
注意:客户端的打包器配置需与服务器端
etc.packet配置保持一致,否则无法正常通信。
网络层(INetwork)负责底层连接的建立与数据收发,目前内置两种实现,构造客户端时按需注入即可:
// TCP 传输(对应服务器 tcp 网关) Client client = new Client(new Due.Network.Tcp(packer), packer); client.Connect("127.0.0.1:3553"); // WebSocket 传输(对应服务器 ws 网关) Client client = new Client(new Due.Network.Ws(packer), packer); client.Connect("ws://127.0.0.1:3553");
due 支持会话安全:客户端与服务端先完成握手,协商出双向 AEAD 会话密钥,之后所有业务消息的 payload 都会被加密,路由与序列号通过 AAD 绑定,防止篡改。
服务端启用会话安全(需配置签名私钥,客户端使用对应公钥验签):
gate := gate.NewGate( gate.WithServer(tcp.NewServer()), gate.WithSessionSecurity(ecc.NewSigner(ecc.WithSignerPrivateKey("keys/gate.pem"))), )
C# 客户端启用会话安全:
using Due; using Due.Security; Packer packer = new Packer(); SecurityOptions security = new SecurityOptions { // 服务端公钥:可以是 PEM 文件路径,也可以是 PEM 内容 Verifier = Verifier.Ecdsa("keys/gate.pub.pem"), // 握手超时时间(毫秒),默认为 5000 HandshakeTimeout = 5000, }; Client client = new Client(new Due.Network.Ws(packer), packer, security); client.OnConnect(c => { // 握手完成后才会触发 OnConnect,此时可以正常收发消息 c.Send(1, 1, new { message = "hello server" }); }); client.Connect("ws://127.0.0.1:3553");
注意:
- 握手使用 X25519 协商临时密钥,通过 HKDF-SHA256 派生双向密钥;客户端会用配置的公钥校验服务端 ServerHello 签名。
- 内置 AEAD 套件为 AES-256-GCM(套件编号 1,纯托管实现,不依赖运行时的
AesGcm);客户端默认只提供该套件,需要与服务端启用的套件有交集。- 只有握手成功后才会触发
OnConnect;握手完成前调用Send会返回false。心跳帧保持明文,不参与会话加密。- 每条连接都会重新握手,重连无需额外处理;握手失败、握手超时或业务帧认证失败都会主动断开连接。
- 服务端使用 RSA 签名时,改用
Verifier.Rsa("keys/gate.pub.pem")(默认 PSS 填充,如需 PKCS#1 v1.5 传入pss: false)。- 如需自定义验签逻辑(例如使用 HMAC 测试签名),可直接传入
HandshakeVerifier委托;如需扩展 AEAD 算法,可实现IAeadSuite并通过SecurityOptions.Suites注入。- 签名算法默认 SHA-256,需与服务端
etc.crypto.ecc.signer.hash配置一致;ECDSA 签名的分隔符默认为空格,与服务端etc.crypto.ecc.signer.delimiter配置一致。
仓库通过 GitHub Actions 自动发布版本,工作流文件为 release.yml。
发布新版本只需推送 v* 标签:
git tag v1.0.0 git push origin v1.0.0
工作流会自动执行:
- 校验标签格式;
- 使用 .NET 8 还原并构建解决方案(Release);
- 将客户端源码打包为
due-client-csharp-<tag>.zip; - 创建 GitHub Release、生成发布说明并上传压缩包;同名 Release 已存在时覆盖上传产物。
也可以在 GitHub Actions 页面手动触发 Release 工作流并填写标签(标签不存在时会基于当前提交创建)。
发布产物解压后可直接通过 dotnet build 使用。