C++服务器说明文档


本教程基于libuv库搭建

基本结构

C++结构

netbus:服务器的启动的入口,启动libuv的循环,并附带以下功能:

  1. 创建缓存区,用于管理内存和内存分配
  2. 提供TCP和UDP和Websocket的监听入口
  3. 接收UDP和TCP的数据,并创建好session
  4. 对TCP的长短包进行处理,并根据包长进行解包,形成完整的单个数据

proto_man:protobuf协议相关,主要负责:

  1. 对netbus发来的数据进行解包,解出包含stype,ctype,utag,body的包体,根据body的不同,还会形成不同的数据类型,如protobuf为message,Json协议是字符串。
  2. 对stype,ctype,utag,body数据提供打包函数,形成完整单个数据包发送给Service

service_man:管理服务,各个服务器在此注册服务,并管理各个service,收到消息或断开链接时会调用对应service的函数

service:各个服务的基类,需要实现接收响应函数,断开连接响应函数,连接响应函数

session:保存utag和uid和是否客户端

session_uv:tcp的session,提供链接的管理,保存了对应客户端的handle,并且拥有以下功能:

  1. 根据protobuf还是websocket来发送打好的数据包
  2. 关闭连接
  3. 保存用户ip和端口

udp_session:udp的session,本质上不是链接,保存客户端的ip和端口,拥有发送数据包的功能。

tcp_protocol:给tcp的整包提供读取header的函数,给tcp提供打包函数(前面附上包长)

ws_protocol:websocket相关,提供了握手函数,读取ws的header的函数,mask函数,按照ws的格式发送数据函数

lua导出

日志

支持多参数,多类型
print(str)
Logger.debug(str)
Logger.warning(str)
Logger.error(str)

mysql

Mysql.connect(ip, port, db_name, uname, upwd, on_open_cb)
Mysql.close(conn)
Mysql.query(conn, cmd, on_lua_query_cb)

redis

Redis.connect(ip, port, on_open_cb)
Redis.close_redis(conn)
Redis.query(conn, cmd, on_lua_query_cb)

netbus

Netbus.udp_listen(port)
Netbus.tcp_listen(port)
Netbus.ws_listen(port)
Netbus.tcp_connect(ip, port, on_tcp_connected)

proto_man

stype,ctype,utag = RawCmd.read_header(raw_cmd)
RawCmd.set_utag(raw_cmd)
message = RawCmd.read_body(raw_cmd)

Scheduler

timer = Scheduler.schedule(on_lua_repeat_timer, after_msec, repeat_count, repeat_msec)
timer = Scheduler.once(on_lua_repeat_timer, repeat_msec)
Scheduler.cancel(timer)

Service

Service.register(stype, service)
Service.register_with_raw(stype, service) 直接转发服务

定义Service

function on_logic_recv_cmd(s, msg)
	end
end

function on_gateway_disconnect(s, stype) 
end

function on_gateway_connect(s, stype)
end
local logic_service = {
	on_session_recv_cmd = on_logic_recv_cmd,
	on_session_disconnect = on_gateway_disconnect,
	on_session_connect = on_gateway_connect
}

session

Session.close(session)
Session.send_msg(session,table(cmd_msg))
Session.send_raw_cmd(session, raw_cmd)
ip,port = Session.get_address(session)
Session.set_utag(session, utag)
utag = Session.get_utag(session)
Session.set_uid(s, uid)
Session.asclient(s, as_client)
Session.udp_send_msg(ip, port, table(cmd_msg))

utils

stamp = Utils.timestamp()
stamp = Utils.timestamp_today()
stamp = Utils.timestamp_yesterday()

通用模块

  1. 日志模块
  2. 定时器模块
  3. 内存分配器模块
  4. 小内存分配器模块
  5. 时间戳

业务逻辑

服务器类型

网关服务器:只负责转发数据
用户服务器:处理登录请求,管理用户数据
系统服务器:处理游戏系统的服务,管理游戏数据
逻辑服务器:处理游戏内的同步

流程

每个服务器都有一个main.lua和service.lua,对应一个服务号,其中main.lua主要开启tcp,udp或websocket监听,并注册服务方便接收客户端传过来的对应数据。service.lua主要定义了该服务接收数据后的响应、客户端断开连接后的响应。
具体的业务逻辑通过service.lua进行转发,一个命令号创建一个脚本,编写对应的响应函数。

  1. gateway:需要注册所有服务,因为需要接收所有数据并转发,但注册的时候调用的是register_with_raw,所以不需要解包。另外需要编写一个定时器来检查与其他服务器的连接,当接收到登录请求的时候,需要判断是否已经有人登陆;发送其他数据的时候,判断登录状态(通过uid)。当用户断线的时候,需要对session做清理,并通知所有其他服务器。

  2. authserver:管理用户数据,实现登录,修改用户数据,账号的升级,登出的功能,发送用户数据给客户端。

  3. systemserver:管理游戏大厅数据,实现金币、经验等游戏数据的获取,修改,每日登陆奖励等。

  4. logicserver:

  • 管理房间内玩家的数据,实现逻辑服务器的登录,断开链接的响应,进入和退出比赛的响应,与最重要的同步。
  • 玩家在该服务器上都有一个player的对象,并用房间类match_mgr来管理一局比赛的玩家,该服务器主要使用面向对象来编程。
  • 每个玩家或属于一个房间,或处于游荡状态。当玩家点击匹配的时候会进入房间,当房间满了就开始比赛,同时开启帧同步的定时器。
  • logicserver单独监听udp端口,帧同步不走网关,当满足条件时才响应请求。

文章作者: 微笑紫瞳星
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 微笑紫瞳星 !
  目录