当前位置: 首页 > 工具软件 > einx > 使用案例 >

einx 用于游戏服务器的golang框架

黄彬
2023-12-01

einx 是一个由 golang 编写的用于游戏服务器或者应用服务器的开源框架。使用简便,便于初级程序员进行逻辑开发,同时einx能够灵活扩展,开发团队可根据需求设计网络拓扑.

github地址:https://github.com/Cyinx/einx

特性:

*  支持简单类型序列化与反序列化的RPC
*  高性能与高精度的定时器
*  支持业务模块化

----------------------------------------------------

* einx/db 组件化数据库相关操作
* einx/network 组件化网络IO
* einx/log 异步日志库
* einx/timer 时间轮定时器
* einx/module 模块
* einx/component 组件
* einx/lua 脚本相关操作
---------------
  每个模块有且仅有一个goroutine用于处理被投递到本模块中的消息,在模块中的逻辑不需要考虑同步问题,简化了逻辑开发难度,模块与模块之间可以通过RPC交互

使用 einx 搭建一个简单的服务器
----------------------------------
安装 einx

go get github.com/go-sql-driver/mysql
go get github.com/yuin/gopher-lua
go get github.com/Cyinx/einx

创建一个简单的einx例子:

package main

import (
    "github.com/Cyinx/einx"
    "github.com/Cyinx/einx/slog"
)
func main() {
    slog.SetLogPath("log/game_server/")
    slog.LogInfo("game_server", "start server...")
    slog.LogInfo("game_server", "hello world...")
    einx.Run()
    einx.Close()
}

einx的任务核心是module,module中可以添加各种component作为组件:


Cyinx/einx/network    网络相关的component
Cyinx/einx/db        数据库相关的component

创建一个TCPServer的component管理器:

package clientmgr

import (
    "github.com/Cyinx/einx"
    "github.com/Cyinx/einx/slog"
    "msg_def"
)

type Agent = einx.Agent
type AgentID = einx.AgentID
type EventType = einx.EventType
type Component = einx.Component
type ComponentID = einx.ComponentID

type ClientMgr struct {
    client_map map[AgentID]Agent
    tcp_link   Component
}

var Instance = &ClientMgr{
    client_map: make(map[AgentID]Agent),
}

func (this *ClientMgr) GetClient(agent_id AgentID) (Agent, bool) {
    client, ok := this.client_map[agent_id]
    return client, ok
}

func (this *ClientMgr) OnLinkerConneted(id AgentID, agent Agent) {
    this.client_map[id] = agent //新连接连入服务器
}

func (this *ClientMgr) OnLinkerClosed(id AgentID, agent Agent) {
    delete(this.client_map, id) //连接断开
}

func (this *ClientMgr) OnComponentError(c Component, err error) {

}

func (this *ClientMgr) OnComponentCreate(id ComponentID, component Component) {
    this.tcp_link = component
    component.Start()
    slog.LogInfo("tcp", "Tcp sever start success")
}


创建一个逻辑module,并将TcpServer管理器加入到module之中,服务器就可以启动,并监听2345端口的请求
 

package main

import (
    "clientmgr"
    "github.com/Cyinx/einx"
    "github.com/Cyinx/einx/slog"
)
var logic = einx.GetModule("logic")
func main() {
    slog.SetLogPath("log/game_server/")
    logic.AddTcpServer(":2345", clientmgr.Instance)
    slog.LogInfo("game_server", "start server...")
    einx.Run()
    einx.Close()
}

注册消息handler与Rpc:
注册消息handler需要事先注册一个Message:
 

package msg_def

import (
    "github.com/Cyinx/einx/network"
    "protobuf_gen"
)

type VersionCheck = pbgen.VersionCheck

var VersionCheckMsgID = network.RegisterMsgProto(uint16(pbgen.MainMsgID_GENERAL_MSG),
    uint16(pbgen.HandlerMsgID_VERSION_CHECK),
    (*VersionCheck)(nil))

在注册RPC时,使用字符串作为RPC名,注册handler时,需要使用之前注册的MsgID

import (
    "msg_def"
)
var logic = einx.GetModule("logic")
func InitDBHandler() {
    logic.RegisterRpcHandler("testRpc", testRpc)
    logic.RegisterHandler(msg_def.VersionCheckMsgID, CheckVersion)
}

func testRpc(sender interface{}, args []interface{}) {

}

func CheckVersion(agent Agent, args interface{}) {
    version_check_msg := args.(*msg_def.VersionCheck)    
}

注册定时器使用module.AddTimer函数,返回值为timerID,如果要提前停止timer,可以执行module.RemoveTimer(timerid):

import (
    "msg_def"
)
var logic = einx.GetModule("logic")
var testTimerID uint64 = 0

func InitDBHandler() {
    logic.RegisterRpcHandler("testRpc", testRpc)
    logic.RegisterHandler(msg_def.VersionCheckMsgID, CheckVersion)
}

func testRpc(sender interface{}, args []interface{}) {
    if testTimerID != 0 {
      logic.RemoveTimer(testTimerID)
    }
}

func TestTimer(args []interface{}) {
    testTimerID = 0
}

func CheckVersion(agent Agent, args interface{}) {
    version_check_msg := args.(*msg_def.VersionCheck)    
    testTimerID = logic.AddTimer(1000,TestTimer,1,2,"测试")
}

 类似资料: