# server **Repository Path**: cobra/server ## Basic Information - **Project Name**: server - **Description**: golang基于微服务实现的游戏服务端 - **Primary Language**: Go - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-08-30 - **Last Updated**: 2020-12-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # goxiang2 ## 简单描述 * golang基于微服务实现的棋牌服务端 by jkkkls@aliyun.com * 基于beego和ace模板实现的[web管理后台](https://gitee.com/goxiang2/web) ## todo 1. 文档 2. 完善服务健康 3. 完善单元测试 4. 完善示例代码 ## 模块说明 * master 服务管理 * master_cli 服务管理客户端 * game 服务集合逻辑 * goxiang2/web web后台 ## srv_gate客户端登陆流程 * 握手,客户端连接上来,需要和服务器进行DH握手生成通讯密钥,加密方式使用aes-cbc-256 1) 服务端发送32字节随机字符串 2) 客户端生成公开参数p(64字节),g(1字节),自己的公钥(64字节),发送给服务端 3) 服务端根据2步骤的参数生成通讯密钥,同时发送自己的公钥给客户端 4) 客户端生成通讯密钥,加密1步骤中的随机字符串,发送给服务端 5) 服务端解密4步骤收到的加密数据和1步骤中随机字符串比较是否一致,一致则握手完成 * 登陆,登陆服务器把玩家登陆信息保存到redis * 游戏消息,如果玩家没有分配game节点,gate根据game负载分配game节点 ## 客户端和gate通讯协议 * 请求 message 数据格式 | 请求 | 长度(byte) | 说明 | | :--: | :------: | :-------------------: | | len | 2 | 消息长度,值为4+n | | cmd | 2 | 操作值 | | seq | 2 | 消息序列号 | | msg | n | 消息打包到protobuf格式的二进制数据 | -------------- * 响应 message 数据格式 | 响应 | 长度(byte) | 说明 | | :--: | :------: | :-------------------: | | len | 2 | 消息长度,值为6+n | | cmd | 2 | 操作值 | | seq | 2 | 消息序列号 | | ret | 2 | 返回值 | | msg | n | 消息打包到protobuf格式的二进制数据 | ## 性能 **_环境_** - **CPU** 2.6GHz inter core i5 - **Memory** 16G - **Go** 1.9.2 - **OS** maxOS **_用法_** - 基于protobuf的简单加法协议 - 客户端和服务器都在本机 - 测试代码:`benchmark/rpc/server/main.go` `benchmark/rpc/client/main.go` **_测试结果_** | 连接数 | 连接并发数 | 请求总数 | 耗时(秒) | | :----: | :---------: | :------: | :------: | | 1 | 1 | 1000000 | 72 | | 1 | 10 | 1000000 | 17 | | 10 | 1 | 1000000 | 19 | | 10 | 10 | 1000000 | 12 | | 10 | 100 | 10000000 | 112 | ## 快速开始(单节点模式) #### 创建gate服务 `service/gate/srv_gate.go` ```go package gate import ( "gitee.com/goxiang2/server/lib/lib_rpc" "log" "net" ) type GxGate struct { } func init() { // 服务注册 lib_rpc.RegisterService("gate", &GxGate{}) } // Run 服务启动函数 func (gate *GxGate) Run() error { port := ":10001" listener, err := net.Listen("tcp", port) if err != nil { log.Printf("lister %s fail\n", port) return err } log.Println("server start, host:", port) for { conn, err1 := listener.Accept() if err1 != nil { log.Printf("server Accept fail, err:", err1.Error()) return err1 } log.Println("new connect", conn.RemoteAddr().String()) go connRun(conn) } } ``` #### 创建登陆服务 `service/login/srv_login.go` ```go package login import ( "gitee.com/goxiang2/server/lib/lib_rpc" lp "gitee.com/goxiang2/server/proto/login" "log" ) type GxLogin struct { } func init() { // 服务注册 lib_rpc.RegisterService("login", &GxLogin{}) } // Run 服务启动函数 func (login *GxLogin) Run() error { return nil } // Login 登陆消息处理函数 func (login *GxLogin) Login(req *lp.LoginReq, rsp *lp.LoginRsp) (uint32, error) { log.Println("-----login----", req.Username, req.Password) rsp.Token = "aaaaaaaaaaaaa" return 0, nil } ``` #### 创建main文件 `example/simpleNode/game/main.go` ```go package main import ( "flag" "gitee.com/goxiang2/server/lib/lib_rpc" _ "gitee.com/goxiang2/server/service/gate" _ "gitee.com/goxiang2/server/service/login" ) var name = flag.String("n", "", "server port name") func main() { flag.Parse() if *name == "" { flag.Usage() return } //没有使用启动master模块,手动注册消息路径 lib_rpc.AddServiceMethod(10001, "Login.Login") //rpc节点服务 lib_rpc.InitNode("", *name) } ``` #### 编译测试代码 ## 运行单节点实例 1. 编译运行game,game其中运行gate和login服务,登陆请求,会由gate服务转发给login服务 ```shell guangbo@guangbodeMac:server$ cd examples/simpleNode/game/ guangbo@guangbodeMac:game$ go build guangbo@guangbodeMac:game$ ./game -n game 2017/11/28 14:19:26 init node game 2017/11/28 14:19:26 register service Gate 2017/11/28 14:19:26 rpc.Register: type Gate has no exported methods of suitable type 2017/11/28 14:19:26 register service Login 2017/11/28 14:19:26 register method Login 2017/11/28 14:19:26 gate start, host: :10001 2017/11/28 14:19:55 new connect 127.0.0.1:53614 2017/11/28 14:19:55 -----login---- guangbo 123123 2017/11/28 14:20:05 -----login---- guangbo 123123 ``` 2. 编译c++测试代码,需要实现准备openssl环境 `examples/simpleNode/client/main.cpp` ```shell guangbo@guangbodeMac:server$ cd examples/simpleNode/client/ guangbo@guangbodeMac:client$ g++ -I ~/Downloads/openssl-1.0.2l/include -I /usr/local/include -L/usr/local/lib -lcrypto -lssl -lprotobuf -o client main.cpp login.pb.cc guangbo@guangbodeMac:client$ ./client handshake success regsiter result,cmd:10001, seq: 1, ret: 0, token: aaaaaaaaaaaaa regsiter result,cmd:10001, seq: 2, ret: 0, token: aaaaaaaaaaaaa ```