einx: 一个用Go构建的游戏服务器

原文作者:Cyinx

einx

a framework in golang for game server or app server.

a example server for einx (https://github.com/Cyinx/game_server_einx)


einx 是一个由 golang 编写的用于游戏服务器或者应用服务器的开源框架。

设计核心:

  • 模块与组件的组合机制,模块是逻辑核心。
  • lua脚本
  • 按业务分离逻辑

  • einx/db 组件化数据库相关操作
  • einx/network 组件化网络IO,目前只支持TCP
  • einx/log 异步日志库
  • einx/timer 时间轮定时器
  • einx/module 模块
  • einx/component 组件
  • einx/lua 脚本相关操作

模块与组件

每个模块有且仅有一个goroutine用于处理被投递到本模块中的消息,在模块中的逻辑不需要考虑同步问题,简化了逻辑开发难度,模块与模块之间可以通过RPC交互

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

首先安装 einx

git clone https://github.com/Cyinx/einx.git

创建一个简单的einx例子:

package mainimport (	"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 clientmgrimport (	"github.com/Cyinx/einx"
	"github.com/Cyinx/einx/slog"
	"msg_def")type Agent = einx.Agenttype AgentID = einx.AgentIDtype EventType = einx.EventTypetype Component = einx.Componenttype ComponentID = einx.ComponentIDtype 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 mainimport (	"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_defimport (	"github.com/Cyinx/einx/network"
	"protobuf_gen")type VersionCheck = pbgen.VersionCheckvar 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 = 0func 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,"测试")
}

版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢。

原文发布于微信公众号 - Golang语言社区(Golangweb)

原文发表时间:2018-10-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏搜云库

CentOs7.3 ssh 免密登录

环境 三台虚拟机(IP): 192.168.252.121 192.168.252.122 192.168.252.123 1.修改主机名 修改三台主机名,以此...

38650
来自专栏自动化测试实战

接口测试框架——第一篇

35360
来自专栏Spark学习技巧

重磅:Flume1-7结合kafka讲解

本文主要是将flume监控目录,文件,kafka Source,kafka sink,hdfs sink这几种生产中我们常用的flume+kafka+hadoo...

76170
来自专栏程序员同行者

Django Rest Framework-介绍

55840
来自专栏Debian社区

Debian Jessie、Stretch 下安装配置 PHP7.2

PHP 7.2.0 已于 2017 年11月30日正式发布GA版,大家可以第一时间尝鲜了。这里我们介绍如何在 Debian 9 “Stretch” 上安装配置 ...

27520
来自专栏曾倩倩的专栏

su命令cannot set groups: Operation not permitted的解决方法

问题场景: user_00@hadoop-10-125-224-102:> su root Password: su: cannot set groups:...

71580
来自专栏FreeBuf

Kali Shellter 5.1:动态ShellCode注入工具 绕过安全软件

或许你还在为无法绕过反病毒软件获得Meterpreter shell而懊恼,试试Shellter 5.1吧。 首先需要获取一个正常的Windows exe可执行...

32260
来自专栏pangguoming

kafka 主要内容介绍

根据官网的介绍,ApacheKafka®是一个分布式流媒体平台,它主要有3种功能:

14350
来自专栏小狼的世界

在Centos 5.2下编译安装LAMP

首先使用Virtualbox安装一台CentOS 5.2的虚拟机,网络连接采用 Host-only Adapter,这样主客机之间可以互相访问,但是客机不能够上...

11220
来自专栏散尽浮华

linux系统下的权限知识梳理

下面对linux系统下的有关权限操作命令进行了梳理总结,并配合简单实例进行说明。 linux中除了常见的读(r)、写(w)、执行(x)权限以外,还有其他的一些特...

31960

扫码关注云+社区

领取腾讯云代金券