main.go代码如下

    1. package main
    2. import (
    3. "flag"
    4. "server/conf"
    5. "server/game"
    6. "server/gate"
    7. "server/login"
    8. _ "time"
    9. _ "FenDZ/glog-master"
    10. _ "github.com/dop251/goja" // JS 解析器
    11. "github.com/name5566/leaf"
    12. lconf "github.com/name5566/leaf/conf"
    13. )
    14. func init() {
    15. // 初始化 日志系统
    16. flag.Set("alsologtostderr", "true") // 日志写入文件的同时,输出到stderr
    17. flag.Set("log_dir", "./log") // 日志文件保存目录
    18. flag.Set("v", "3") // 配置V输出的等级。
    19. flag.Parse()
    20. return
    21. }
    22. func main() {
    23. // 加载配置
    24. lconf.LogLevel = conf.Server.LogLevel
    25. lconf.LogPath = conf.Server.LogPath
    26. lconf.LogFlag = conf.LogFlag
    27. lconf.ConsolePort = conf.Server.ConsolePort
    28. lconf.ProfilePath = conf.Server.ProfilePath
    29. // 注册模块
    30. leaf.Run(
    31. game.Module,
    32. gate.Module,
    33. login.Module,
    34. )
    35. }

    知识点

    • 消息配置,实现不同功能对应不同的消息,防止数据处理混乱。文件:serveer\msg\msg.go
    1. package msg
    2. import (
    3. "github.com/name5566/leaf/network"
    4. "github.com/name5566/leaf/network/json"
    5. )
    6. var Processorbak network.Processor
    7. // 使用默认的 JSON 消息处理器(默认还提供了 protobuf 消息处理器)
    8. var Processor = json.NewProcessor()
    9. func init() {
    10. // 这里我们注册了一个 JSON 消息 Test
    11. Processor.Register(&Test{})
    12. // 注册登陆协议
    13. Processor.Register(&UserLogin{})
    14. }
    15. // 一个结构体定义了一个 JSON 消息的格式
    16. // 消息名为 Test
    17. type Test struct {
    18. Name string
    19. }
    20. // 用户登陆的协议
    21. type UserLogin struct {
    22. LoginName string
    23. LoginPW string
    24. }
    • 配置路由:实现将消息Test、UserLogin分别发给Game和Login模块。文件:server\gate\router.go
    1. package gate
    2. import (
    3. "server/game"
    4. "server/login"
    5. "server/msg"
    6. )
    7. func init() {
    8. // 这里指定消息 Test 路由到 game 模块
    9. // 模块间使用 ChanRPC 通讯,消息路由也不例外
    10. msg.Processor.SetRouter(&msg.Test{}, game.ChanRPC)
    11. // 路由分发数据到login
    12. msg.Processor.SetRouter(&msg.UserLogin{}, login.ChanRPC)
    13. }
    • game模块处理消息。文件位置:server\game\internal\handler.go
    1. package internal
    2. import (
    3. "reflect"
    4. "server/msg"
    5. "github.com/name5566/leaf/gate"
    6. "github.com/name5566/leaf/log"
    7. )
    8. func init() {
    9. // 向当前模块(game 模块)注册 Test 消息的消息处理函数 handleTest
    10. handler(&msg.Test{}, handleTest)
    11. }
    12. // 异步处理
    13. func handler(m interface{}, h interface{}) {
    14. skeleton.RegisterChanRPC(reflect.TypeOf(m), h)
    15. }
    16. // 消息处理
    17. func handleTest(args []interface{}) {
    18. // 收到的 Test 消息
    19. m := args[0].(*msg.Test)
    20. // 消息的发送者
    21. a := args[1].(gate.Agent)
    22. // 输出收到的消息的内容
    23. log.Debug("hello game %v", m.Name)
    24. // 给发送者回应一个 Test 消息
    25. a.WriteMsg(&msg.Test{
    26. Name: "client",
    27. })
    28. }
    • login模块处理消息。文件位置:server\login\internal\handler.go
    1. package internal
    2. import (
    3. "reflect"
    4. "server/msg"
    5. "github.com/name5566/leaf/gate"
    6. "github.com/name5566/leaf/log"
    7. )
    8. func handleMsg(m interface{}, h interface{}) {
    9. skeleton.RegisterChanRPC(reflect.TypeOf(m), h)
    10. }
    11. func init() {
    12. // 向当前模块(login 模块)注册 Test 消息的消息处理函数 handleTest
    13. handleMsg(&msg.UserLogin{}, handleTest)
    14. }
    15. // 消息处理
    16. func handleTest(args []interface{}) {
    17. // 收到的 Test 消息
    18. m := args[0].(*msg.UserLogin)
    19. // 消息的发送者
    20. a := args[1].(gate.Agent)
    21. // 1 查询数据库--判断用户是不是合法
    22. // 2 如果数据库返回查询正确--保存到缓存或者内存
    23. // 输出收到的消息的内容
    24. log.Debug("Test login %v", m.LoginName)
    25. // 给发送者回应一个 Test 消息
    26. a.WriteMsg(&msg.Test{
    27. Name: "client",
    28. })
    29. }
    • TCP_模拟客户端
    1. package main
    2. import (
    3. "encoding/binary"
    4. "net"
    5. )
    6. func main() {
    7. conn, err := net.Dial("tcp", "127.0.0.1:8888")
    8. if err != nil {
    9. panic(err)
    10. }
    11. // Test 消息(JSON 格式)
    12. // 对应游戏服务器 Test 消息结构体
    13. data := []byte(`{
    14. "Test": {
    15. "Name": "leaf"
    16. }
    17. }`)
    18. // len + data
    19. m := make([]byte, 2+len(data))
    20. // 默认使用大端序
    21. binary.BigEndian.PutUint16(m, uint16(len(data)))
    22. copy(m[2:], data)
    23. // 发送消息
    24. conn.Write(m)
    25. if true {
    26. data := []byte(`{
    27. "UserLogin": {
    28. "LoginName": "leaf",
    29. "LoginPW" :"sss"
    30. }
    31. }`)
    32. // len + data
    33. m := make([]byte, 2+len(data))
    34. // 默认使用大端序
    35. binary.BigEndian.PutUint16(m, uint16(len(data)))
    36. copy(m[2:], data)
    37. // 发送消息
    38. conn.Write(m)
    39. }
    40. }

    golang leaf调试Game、Login模块收发信息 - 图1