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.6 KiB

服务端如何写数据到客户端

概述

nnet库提供了多种方式将数据从服务端写入到客户端支持任意类型的数据并自动匹配编解码器进行编码。

方式一:写入字节数据(基础方式)

func handler(ctx context.Context) error {
    // 直接写入字节数据
    data := []byte("Hello, World!")
    return ctx.Write(data)
}

方式二:写入字符串

func handler(ctx context.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 context.Context) error {
    // 写入结构体自动使用JSON编码
    resp := Response{
        Code:    200,
        Message: "success",
        Data:    map[string]interface{}{"user_id": 123},
    }
    return ctx.WriteAny(resp)
}

指定编解码器

func handler(ctx context.Context) error {
    resp := Response{
        Code:    200,
        Message: "success",
    }
    
    // 使用JSON编解码器
    ctx.WriteAnyWithCodec(resp, "json")
    
    // 使用MessagePack编解码器
    ctx.WriteAnyWithCodec(resp, "msgpack")
    
    // 使用Protobuf编解码器需要实现proto.Message接口
    ctx.WriteAnyWithCodec(resp, "protobuf")
    
    return nil
}

方式四:协议层编码(可选)

如果启用了协议层编码数据会先使用编解码器编码然后再使用协议编码如nnet协议的Magic、长度、校验和等

配置协议层编码

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

server, err := nnet.NewServer(cfg)

使用示例

func handler(ctx context.Context) error {
    // 数据会先使用JSON编码然后使用协议编码如nnet协议
    resp := Response{Code: 200, Message: "success"}
    return ctx.WriteAny(resp)
}

完整示例

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", getUserHandler)
    server.Router().RegisterString("list_users", listUsersHandler)

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

// 处理器1返回单个用户使用默认编解码器binary
func getUserHandler(ctx ctxpkg.Context) error {
    user := User{
        ID:   1,
        Name: "Alice",
    }
    
    resp := Response{
        Code: 200,
        Data: user,
    }
    
    // 自动使用JSON编码
    return ctx.WriteAny(resp)
}

// 处理器2返回用户列表
func listUsersHandler(ctx ctxpkg.Context) error {
    users := []User{
        {ID: 1, Name: "Alice"},
        {ID: 2, Name: "Bob"},
    }
    
    resp := Response{
        Code: 200,
        Data: users,
    }
    
    return ctx.WriteAny(resp)
}

// 处理器3使用指定的编解码器
func getUserWithMsgpack(ctx ctxpkg.Context) error {
    user := User{ID: 1, Name: "Alice"}
    resp := Response{Code: 200, Data: user}
    
    // 使用MessagePack编码
    return ctx.WriteAnyWithCodec(resp, "msgpack")
}

支持的编解码器

  1. JSON(可选,默认是 binary

    • 支持所有可序列化的Go类型
    • 使用标准库的encoding/json
  2. Binary

    • 支持基本数值类型和字节数组
    • 使用二进制编码
  3. Protobuf

    • 需要实现proto.Message接口
    • 使用Google Protocol Buffers
  4. MessagePack

    • 支持所有可序列化的Go类型
    • 比JSON更紧凑的二进制格式

编解码器注册

服务器会自动注册以下编解码器:

  • json - JSON编解码器可选默认为 binary
  • binary - 二进制编解码器
  • protobuf - Protobuf编解码器
  • `