main.go代码如下
package mainimport ("flag""server/conf""server/game""server/gate""server/login"_ "time"_ "FenDZ/glog-master"_ "github.com/dop251/goja" // JS 解析器"github.com/name5566/leaf"lconf "github.com/name5566/leaf/conf")func init() {// 初始化 日志系统flag.Set("alsologtostderr", "true") // 日志写入文件的同时,输出到stderrflag.Set("log_dir", "./log") // 日志文件保存目录flag.Set("v", "3") // 配置V输出的等级。flag.Parse()return}func main() {// 加载配置lconf.LogLevel = conf.Server.LogLevellconf.LogPath = conf.Server.LogPathlconf.LogFlag = conf.LogFlaglconf.ConsolePort = conf.Server.ConsolePortlconf.ProfilePath = conf.Server.ProfilePath// 注册模块leaf.Run(game.Module,gate.Module,login.Module,)}
知识点
- 消息配置,实现不同功能对应不同的消息,防止数据处理混乱。文件:serveer\msg\msg.go
package msgimport ("github.com/name5566/leaf/network""github.com/name5566/leaf/network/json")var Processorbak network.Processor// 使用默认的 JSON 消息处理器(默认还提供了 protobuf 消息处理器)var Processor = json.NewProcessor()func init() {// 这里我们注册了一个 JSON 消息 TestProcessor.Register(&Test{})// 注册登陆协议Processor.Register(&UserLogin{})}// 一个结构体定义了一个 JSON 消息的格式// 消息名为 Testtype Test struct {Name string}// 用户登陆的协议type UserLogin struct {LoginName stringLoginPW string}
- 配置路由:实现将消息Test、UserLogin分别发给Game和Login模块。文件:server\gate\router.go
package gateimport ("server/game""server/login""server/msg")func init() {// 这里指定消息 Test 路由到 game 模块// 模块间使用 ChanRPC 通讯,消息路由也不例外msg.Processor.SetRouter(&msg.Test{}, game.ChanRPC)// 路由分发数据到loginmsg.Processor.SetRouter(&msg.UserLogin{}, login.ChanRPC)}
- game模块处理消息。文件位置:server\game\internal\handler.go
package internalimport ("reflect""server/msg""github.com/name5566/leaf/gate""github.com/name5566/leaf/log")func init() {// 向当前模块(game 模块)注册 Test 消息的消息处理函数 handleTesthandler(&msg.Test{}, handleTest)}// 异步处理func handler(m interface{}, h interface{}) {skeleton.RegisterChanRPC(reflect.TypeOf(m), h)}// 消息处理func handleTest(args []interface{}) {// 收到的 Test 消息m := args[0].(*msg.Test)// 消息的发送者a := args[1].(gate.Agent)// 输出收到的消息的内容log.Debug("hello game %v", m.Name)// 给发送者回应一个 Test 消息a.WriteMsg(&msg.Test{Name: "client",})}
- login模块处理消息。文件位置:server\login\internal\handler.go
package internalimport ("reflect""server/msg""github.com/name5566/leaf/gate""github.com/name5566/leaf/log")func handleMsg(m interface{}, h interface{}) {skeleton.RegisterChanRPC(reflect.TypeOf(m), h)}func init() {// 向当前模块(login 模块)注册 Test 消息的消息处理函数 handleTesthandleMsg(&msg.UserLogin{}, handleTest)}// 消息处理func handleTest(args []interface{}) {// 收到的 Test 消息m := args[0].(*msg.UserLogin)// 消息的发送者a := args[1].(gate.Agent)// 1 查询数据库--判断用户是不是合法// 2 如果数据库返回查询正确--保存到缓存或者内存// 输出收到的消息的内容log.Debug("Test login %v", m.LoginName)// 给发送者回应一个 Test 消息a.WriteMsg(&msg.Test{Name: "client",})}
- TCP_模拟客户端
package mainimport ("encoding/binary""net")func main() {conn, err := net.Dial("tcp", "127.0.0.1:8888")if err != nil {panic(err)}// Test 消息(JSON 格式)// 对应游戏服务器 Test 消息结构体data := []byte(`{"Test": {"Name": "leaf"}}`)// len + datam := make([]byte, 2+len(data))// 默认使用大端序binary.BigEndian.PutUint16(m, uint16(len(data)))copy(m[2:], data)// 发送消息conn.Write(m)if true {data := []byte(`{"UserLogin": {"LoginName": "leaf","LoginPW" :"sss"}}`)// len + datam := make([]byte, 2+len(data))// 默认使用大端序binary.BigEndian.PutUint16(m, uint16(len(data)))copy(m[2:], data)// 发送消息conn.Write(m)}}

