在开始本范例之前,请确保已经获取了 和 Leafserver 并且正确配置(否则请阅读 中相关内容)。

编辑 Leafserver 中的文件 msg/msg.go

我们在 msg.go 相同目录下创建一个 test.proto 文件,内容如下:

  1. message Hello {
  2. required string name = 1;
  3. }

这里定义了一个 Hello 消息。编译 test.proto 文件(对此不了解?请先阅读《》一文)得到 test.pb.go 文件(假定在 test.proto 当前目录下执行以下命令):

  1. protoc --go_out=. test.proto

现在开始注册我们的 Hello 消息。编辑 msg.go 文件,修改 init 函数:

  1. func init() {
  2. // 这里我们注册了消息 Hello
  3. Processor.Register(&Hello{})
  4. }

一切就绪,我们现在可以在 game 模块中处理 Hello 消息了。打开 LeafServer game/internal/handler.go,敲入如下代码:

  1. package internal
  2. import (
  3. "github.com/golang/protobuf/proto"
  4. "github.com/name5566/leaf/gate"
  5. "reflect"
  6. "server/msg"
  7. )
  8. // 向当前模块(game 模块)注册 Hello 消息的消息处理函数 handleHello
  9. handler(&msg.Hello{}, handleHello)
  10. }
  11. func handler(m interface{}, h interface{}) {
  12. skeleton.RegisterChanRPC(reflect.TypeOf(m), h)
  13. }
  14. func handleHello(args []interface{}) {
  15. // 收到的 Hello 消息
  16. m := args[0].(*msg.Hello)
  17. // 消息的发送者
  18. a := args[1].(gate.Agent)
  19. // 输出收到的消息的内容
  20. log.Debug("hello %v", m.GetName())
  21. // 给发送者回应一个 Hello 消息
  22. a.WriteMsg(&msg.Hello{
  23. })
  24. }

到这里,一个简单的范例就完成了。

在 Leaf 中,默认的 Protobuf Processor 将一个完整的 Protobuf 消息定义为如下格式:

  1. -------------------------
  2. | id | protobuf message |
  3. -------------------------

其中 id 为 2 个字节。如果你选择使用 TCP 协议时,在网络中传输的消息格式如下:

  1. -------------------------------
  2. | len | id | protobuf message |
  3. -------------------------------

如果你选择使用 WebSocket 协议时,发送的消息格式如下:

常见问题

首先,Protobuf id 是 Leaf 的 Protobuf Processor 自动生成的。生成规则是从 0 开始,第一个注册的消息 ID 为 0,第二个注册的消息 ID 为 1,以此类推。例如:

  1. func init() {
  2. Processor.Register(&MsgA{}) // 消息 ID 为 0
  3. Processor.Register(&MsgB{}) // 消息 ID 为 1
  4. Processor.Register(&MsgC{}) // 消息 ID 为 2
  5. }

由于消息 ID 是服务器生成的,因此建议服务器导出消息 ID 给客户端使用。这里提供一个简单的思路,假定客户端使用 Lua,这时候服务器可以导出消息 ID 为一个 Lua 源文件,此源文件中包含一个 table,可能内容如下:

  1. msg = {
  2. [0] = "msg.MsgA",
  3. [1] = "msg.MsgB",
  4. [2] = "msg.MsgC",
  5. }

Lua 客户端加载此 Lua 源文件,得到 msg table,然后就可以从消息 ID(网络中过来的消息)获取到消息了。当然,各位同学需要按照自己的实际情况来做实际的处理。

为了导出消息 ID 给客户端,Leaf 的 Protobuf Processor 提供了方法:

    通过此方法,我们可以遍历所有 Protobuf 消息,然后(比如说按上述方式)导出消息 ID 给客户端使用。