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()
}