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.

4.9 KiB

服务端写数据到客户端 - 问题解答

问题

  1. 服务端如何写数据到客户端?
  2. 是否支持any类型
  3. 通过协议自动匹配编码器?

答案

1. 服务端如何写数据到客户端?

nnet库提供了多种方式将数据从服务端写入到客户端

方式一:直接写入字节数据

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)
}

2. 是否支持any类型

是的,完全支持!

nnet库支持写入任意Go类型

  • 结构体struct
  • 映射map
  • 切片slice
  • 数组array
  • 基本类型int, string, bool等
  • 接口类型interface{}

使用ctx.WriteAny(data)方法nnet会自动

  1. 检测数据类型
  2. 选择合适的编解码器
  3. 编码数据
  4. 写入客户端

3. 通过协议自动匹配编码器?

是的,完全支持!

nnet库提供了自动编解码器匹配功能:

自动匹配机制

  1. 默认编解码器:根据配置自动选择默认编解码器(库默认 binary

    cfg := &nnet.Config{
        Codec: &nnet.CodecConfig{
           DefaultCodec: "json",  // 显式使用JSON
        },
    }
    
  2. 自动编码:使用WriteAny时,自动使用默认编解码器(默认 binary

    ctx.WriteAny(data)  // 自动使用JSON编码
    
  3. 指定编解码器:可以指定使用哪个编解码器

    ctx.WriteAnyWithCodec(data, "json")      // 使用JSON
    ctx.WriteAnyWithCodec(data, "msgpack")   // 使用MessagePack
    ctx.WriteAnyWithCodec(data, "protobuf")  // 使用Protobuf
    

协议层编码(可选)

nnet还支持协议层编码,可以在编解码器编码的基础上,再进行协议层编码:

cfg := &nnet.Config{
    Codec: &nnet.CodecConfig{
        DefaultCodec:         "json",
        EnableProtocolEncode: true,  // 启用协议层编码
    },
}

启用后,数据会经过:

  1. 编解码器编码Go对象 → JSON字节数组
  2. 协议编码JSON字节数组 → nnet协议格式包含Magic、长度、校验和等

完整示例

package main

import (
    "github.com/noahlann/nnet"
    ctxpkg "github.com/noahlann/nnet/pkg/context"
)

type User struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
}

type Response struct {
    Code int         `json:"code"`
    Data interface{} `json:"data"`
}

func main() {
    // 配置服务器(启用自动编解码器匹配)
    cfg := &nnet.Config{
        Addr: "tcp://:8080",
        Codec: &nnet.CodecConfig{
            DefaultCodec:         "json",  // 显式使用JSON
            EnableProtocolEncode: false,   // 不启用协议层编码
        },
    }

    // 创建服务器
    server, err := nnet.NewServer(cfg)
    if err != nil {
        panic(err)
    }

    // 注册路由处理器
    server.Router().RegisterString("get_user", func(ctx ctxpkg.Context) error {
        user := User{ID: 1, Name: "Alice"}
        resp := Response{Code: 200, Data: user}
        
        // 方式1自动使用JSON编码推荐
        return ctx.WriteAny(resp)
        
        // 方式2指定使用MessagePack编码
        // return ctx.WriteAnyWithCodec(resp, "msgpack")
        
        // 方式3直接写入字符串
        // return ctx.WriteString("Hello, World!")
    })

    // 启动服务器
    server.Start()
}

支持的编解码器

nnet库自动注册以下编解码器

  • JSON(可选,默认 binary支持所有可序列化的Go类型
  • Binary:支持基本数值类型和字节数组
  • Protobuf:需要实现proto.Message接口
  • MessagePack支持所有可序列化的Go类型

自定义编解码器

// 注册自定义编解码器
server.CodecRegistry().Register("mycodec", myCodec)

// 使用自定义编解码器
ctx.WriteAnyWithCodec(data, "mycodec")

总结

服务端写数据:支持WriteWriteStringWriteAny三种方式 支持any类型完全支持任意Go类型 自动匹配编码器:根据配置自动选择编解码器,也可以手动指定 协议层编码可选地支持协议层编码如nnet协议

所有功能已实现并测试通过!