xingo 单进程服务器入门教程
推荐项目目录结构:
.
├── api 用户自定义协议
│ └── test_api.go
├── client_walk.go 自动化游戏全逻辑测试脚本
├── conf
│ └── server.json 服务器全局配置
├── core 游戏核心逻辑/各种游戏玩法,活动相关逻辑放到这儿
│ ├── aoi.go
│ ├── player.go
│ └── worldmgr.go
├── log 默认日志文件存放路径/日志可按照时间和大小切割
│ ├── server.log
│ ├── server.log.2016-12-20
│ ├── server.log.2016-12-26
├── pb 消息定义
│ ├── msg.pb.go
│ └── msg.proto
├── README.md
├── server.go 服务器主逻辑
推荐clone demo项目到本地:
git clone https://git.oschina.net/viphxin/xingo_demo.git
配置服务器
vim conf/server.json
{ "TcpPort": 8999,//监听端口 "StepPerMs": 2000,//demo逻辑配置,非通用配置项 "PoolSize": 5, //工作队列数 "IsUsePool": true,//是否使用工作队列 "LogLevel": 1, //日志级别 0 ALL 1 DEBUG 2 INFO 3 WARN 4 ERROR 5 FATAL 6 OFF "MaxConn": 2000 //支持最大连接数 }google protobuf消息定义:
message Talk{ string Content=1; }定义一个测试接口api,实现功能世界聊天(广播每个链接发过来的talk消息):
导入xingo
import ( "xingo_demo/pb" "xingo_demo/core" "github.com/golang/protobuf/proto" "github.com/viphxin/xingo/fnet" "github.com/viphxin/xingo/logger" "fmt" )定义api接口:
type TestRouter struct { } /* ping test */ func (this *TestRouter) Api_0(request *fnet.PkgAll) { logger.Debug("call Api_0") // request.Fconn.SendBuff(0, nil) packdata, err := fnet.DefaultDataPack.Pack(0, nil) if err == nil{ request.Fconn.Send(packdata) }else{ logger.Error("pack data error") } } /* 世界聊天 */ func (this *TestRouter) Api_2(request *fnet.PkgAll) { msg := &pb.Talk{} err := proto.Unmarshal(request.Pdata.Data, msg)//解析Talk消息 if err == nil { logger.Debug(fmt.Sprintf("user talk: content: %s.", msg.Content)) pid, err1 := request.Fconn.GetProperty("pid") if err1 == nil{ p, _ := core.WorldMgrObj.GetPlayer(pid.(int32)) p.Talk(msg.Content)//广播 }else{ logger.Error(err1) request.Fconn.LostConnection() } } else { logger.Error(err) request.Fconn.LostConnection() } }
实现自己的xingo server
package main import ( "fmt" "github.com/viphxin/xingo/fserver" "github.com/viphxin/xingo/iface" "github.com/viphxin/xingo/logger" "github.com/viphxin/xingo/utils" "xingo_demo/api" "xingo_demo/core" "os" "os/signal" ) func DoConnectionMade(fconn iface.Iconnection) { logger.Debug("111111111111111111111111") p, _ := core.WorldMgrObj.AddPlayer(fconn) fconn.SetProperty("pid", p.Pid) } func DoConnectionLost(fconn iface.Iconnection) { logger.Debug("222222222222222222222222") pid, _ := fconn.GetProperty("pid") p, _ := core.WorldMgrObj.GetPlayer(pid.(int32)) //移除玩家 core.WorldMgrObj.RemovePlayer(pid.(int32)) //消失在地图 p.LostConnection() } func main() { s := fserver.NewServer() //add api ---------------start TestRouterObj := &api.TestRouter{} s.AddRouter(TestRouterObj)//注册接口api //add api ---------------end //regest callback utils.GlobalObject.OnConnectioned = DoConnectionMade//绑定链接建立处理函数 utils.GlobalObject.OnClosed = DoConnectionLost//绑定链接丢失处理函数 s.Start()//开启服务器 // close c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt, os.Kill) sig := <-c fmt.Println("=======", sig) s.Stop() }