You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
6.0 KiB
6.0 KiB
编解码器和协议集成说明
功能概述
nnet库现在支持:
- ✅ 任意类型数据写入:通过
ctx.WriteAny(data)写入任意Go类型 - ✅ 自动编解码器匹配:根据配置自动选择编解码器(JSON、Binary、Protobuf、MessagePack)
- ✅ 协议层编码:可选地支持协议层编码(如nnet协议的Magic、长度、校验和)
- ✅ 自定义编解码器:支持注册和使用自定义编解码器
服务端写数据到客户端
方式一:写入字节数据(基础方式)
func handler(ctx ctxpkg.Context) error {
data := []byte("Hello, World!")
return ctx.Write(data)
}
方式二:写入字符串
func handler(ctx ctxpkg.Context) error {
return ctx.WriteString("Hello, World!")
}
方式三:写入任意类型(自动编码)⭐ 推荐
type Response struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
}
func handler(ctx ctxpkg.Context) error {
resp := Response{
Code: 200,
Message: "success",
Data: map[string]interface{}{"user_id": 123},
}
// 自动使用配置的默认编解码器(默认是binary)
return ctx.WriteAny(resp)
}
方式四:指定编解码器
func handler(ctx ctxpkg.Context) error {
resp := Response{Code: 200, Message: "success"}
// 使用JSON编解码器
ctx.WriteAnyWithCodec(resp, "json")
// 使用MessagePack编解码器
ctx.WriteAnyWithCodec(resp, "msgpack")
// 使用Protobuf编解码器
ctx.WriteAnyWithCodec(resp, "protobuf")
return nil
}
配置编解码器
基本配置
cfg := &nnet.Config{
Addr: "tcp://:8080",
Codec: &nnet.CodecConfig{
DefaultCodec: "binary", // 默认编解码器(库默认)
EnableProtocolEncode: false, // 是否启用协议层编码
},
}
启用协议层编码
cfg := &nnet.Config{
Addr: "tcp://:8080",
Codec: &nnet.CodecConfig{
DefaultCodec: "json",
EnableProtocolEncode: true, // 启用协议层编码
},
}
启用协议层编码后,数据会经过:
- 编解码器编码:将Go对象编码为字节数组(如JSON)
- 协议编码:将字节数组包装为协议格式(如nnet协议的Magic、长度、校验和)
支持的编解码器
1. JSON(可选,默认为 binary)
// 自动使用JSON编码
ctx.WriteAny(data)
2. Binary
// 使用二进制编码
ctx.WriteAnyWithCodec(data, "binary")
3. Protobuf
// 使用Protobuf编码(需要实现proto.Message接口)
ctx.WriteAnyWithCodec(data, "protobuf")
4. MessagePack
// 使用MessagePack编码
ctx.WriteAnyWithCodec(data, "msgpack")
协议层编码
nnet协议格式
如果启用了协议层编码,数据会按照nnet协议格式编码:
[Magic(4 bytes)][Version(1 byte)][Length(4 bytes)][Data(N bytes)][Checksum(2 bytes)]
- Magic: "NNET" (4字节)
- Version: 协议版本(1字节)
- Length: 数据长度(4字节,大端序)
- Data: 实际数据(N字节)
- Checksum: 校验和(2字节,大端序)
使用示例
cfg := &nnet.Config{
Addr: "tcp://:8080",
Codec: &nnet.CodecConfig{
DefaultCodec: "json",
EnableProtocolEncode: true, // 启用nnet协议编码
},
}
server, _ := nnet.NewServer(cfg)
// 在处理器中
func handler(ctx ctxpkg.Context) error {
resp := Response{Code: 200, Message: "success"}
// 数据会先JSON编码,然后使用nnet协议编码
return ctx.WriteAny(resp)
}
自定义编解码器
实现编解码器接口
type MyCodec struct{}
func (c *MyCodec) Encode(v interface{}) ([]byte, error) {
// 实现编码逻辑
return []byte("encoded"), nil
}
func (c *MyCodec) Decode(data []byte, v interface{}) error {
// 实现解码逻辑
return nil
}
func (c *MyCodec) Name() string {
return "mycodec"
}
注册自定义编解码器
server, _ := nnet.NewServer(cfg)
// 注册自定义编解码器
myCodec := &MyCodec{}
server.CodecRegistry().Register("mycodec", myCodec)
// 使用自定义编解码器
ctx.WriteAnyWithCodec(data, "mycodec")
协议管理器
注册协议
server, _ := nnet.NewServer(cfg)
// 获取协议管理器
protocolManager := server.ProtocolManager()
// 注册nnet协议
nnetProtocol := internalprotocol.NewNNetProtocol("1.0")
protocolManager.Register(nnetProtocol)
获取协议
// 获取协议
protocol, err := protocolManager.Get("nnet", "1.0")
if err != nil {
// 处理错误
}
完整示例
package main
import (
"github.com/noahlann/nnet"
ctxpkg "github.com/noahlann/nnet/pkg/context"
)
type Response struct {
Code int `json:"code"`
Data interface{} `json:"data"`
}
func main() {
// 配置服务器
cfg := &nnet.Config{
Addr: "tcp://:8080",
Codec: &nnet.CodecConfig{
DefaultCodec: "json",
EnableProtocolEncode: false,
},
}
// 创建服务器
server, err := nnet.NewServer(cfg)
if err != nil {
panic(err)
}
// 注册路由
server.Router().RegisterString("hello", func(ctx ctxpkg.Context) error {
// 方式1:写入字符串
ctx.WriteString("Hello, World!")
// 方式2:写入结构体(自动JSON编码)
resp := Response{Code: 200, Data: "success"}
ctx.WriteAny(resp)
// 方式3:使用指定的编解码器
ctx.WriteAnyWithCodec(resp, "msgpack")
return nil
})
// 启动服务器
server.Start()
}
总结
nnet库现在完全支持:
- ✅ 任意类型数据写入(
WriteAny) - ✅ 自动编解码器匹配
- ✅ 协议层编码(可选)
- ✅ 自定义编解码器
- ✅ 向后兼容(支持直接写入字节或字符串)
这大大简化了服务端写数据到客户端的操作,开发者无需手动处理编码逻辑。