游戏服务端通讯框架实现

来源:互联网 发布:mac mini评测2016 编辑:程序博客网 时间:2024/06/06 05:46

从事游戏开发已经有一段时间,一直想写一套属于自己的通讯框架,可迟迟没有动手。

前阵子时间相对充裕,就在网上找了一些服务端架构方面的资料看了下,借鉴以前的游戏通讯引擎,通过研究学习,自己也写出了一套通讯框架,经过验证,可以正常与AS、C++良好的进行通讯。

框架完成后,又闲置了一阵子,一直没有时间继续完善,最近在弄些分布式的东西,于是又想了之前写好的通讯框架,在此总结下实现,以及期间遇到的问题。

下面说说一些相关的设计:

1      技术说明

Ø JDK版本,采用1.6

Ø 基于apache-mina NIO框架

Ø 采用TCP/IP协议,长连接的方式

Ø 与客户端数据交互,采用字节数组

Ø 报文格式:定长报文头(如:协议头1字节,数据为4字节)

Ø 持久化方面,采用mysql数据库,版本5.5

Ø 数据源采用c3p0数据源

 

2      服务器架构设计

2.1 现阶段服务器架构分类

服务器组的架构一般分为两种:第一种是带网关服务器的服务器架构;第二种是不带网关服务器的服务器架构,这两种方案各有利弊。在给出服务器架构设计之前,先对这两种设计方案进行详细的探讨。所谓网关服务器,其实是Gate 服务器,比如GateServer1等。网关服务器的主要职责是将客户端和游戏服务器隔离,客户端程序直接与这些网关服务器通信,并不需要知道具体的游戏服务器内部架构,包括它们的IP、端口、网络通信模型(完成端口或Epoll)等。客户端只与网关服务器相连,通过网关服务器转发数据包间接地与游戏服务器交互。同样地,游戏服务器也不直接和客户端通信,发给客户端的协议都通过网关服务器进行转发。

   

2.2 服务器构架方案

根据网络游戏的规模和设计的不同,每组服务器中服务器种类和数量是不尽相同的。本系统设计出的带网关服务器的服务器组架构如图1 所示。

                             

 

图1 带网关服务器的服务器架构设计方案

 

该设计有以下几点好处:

1、GateServer作为网络通信的中转站,负责维护将内网和外网隔离开,使外部无法直接访问内部服务器,保障内网服务器的安全,一定程度上较少外挂的攻击。

2、网关服务器负责解析数据包、加解密、超时处理和一定逻辑处理,这样可以提前过滤掉错误包和非法数据包。

3、客户端程序只需建立与网关服务器的连接即可进入游戏,无需与其它游戏服务器同时建立多条连接,节省了客户端和服务器程序的网络资源开销。

4、在玩家跳服务器时,不需要断开与网关服务器的连接,玩家数据在不同游戏服务器间的切换是内网切换,切换工作瞬间完成,玩家几乎察觉不到,这保证了游戏的流畅性

和良好的用户体验。

虽然网关服务器带来上述好处,但是,还需要注意以下可能导致负面效果的两个情况:如何避免网关服务器成为高负载情况下的通讯瓶颈问题以及由于网关的单节点故障导致整组服务器无法对外提供服务的问题。上述两个问题可以采用“多网关”技术加以解决。顾名思义,“多网关” 就是同时存在多个网关服务器,比如一组服务器可以配置三台GateServer。当负载较大时,可以通过增加网关服务器来增加网关的总体通讯流量,当一台网关服务器宕机时,它只会影响连接到本服务器的客户端,其它客户端不会受到任何影响。从图1 的服务器架构图可以看出,一组服务器包括GateServer、GameServer、FightServer、MailServer、LogServerS和PaltformServer 等多种服务器。GateServer 就是网关服务器,一般一组服务器会配置3 台GateServer,因为稳定性对于网络游戏运营来说是至关重要的,而服务器宕机等突发事件是游戏运营中所面临的潜在风险,配置多台服务器可以有效地降低单个服务器宕机带来的风险。另外,配置多台网关服务器也是进行负载均衡的有效手段之一。其中,各种服务器的主要功能和彼此之间的数据交互情况如下。

(1)LoginGate

LoginGate 主要负责在玩家登录时维护客户端与LoginServer 之间的网络连接与通讯,对LoginServer 和客户端的通信数据进行加解密、校验。

(2)LoginServer

LoginServer 主要功能是验证玩家的账号是否合法,只有通过验证的账号才能登录游戏。从架构图可以看出, GameServer 会连接LoginServer。玩家登录基本流程是,客户端发送账号和密码到LoginServer 验证,如果验证通过,LoginServer 会给玩家分配一个SessionKey,LoginServer 会把这个SessionKey 发送给客户端、GameServer,在后续的选择角色以后进入游戏过程中,GameServer 将验证SessionKey 合法性,如果和客户端携带的SessionKey 不一致,将无法成功获取到角色或者进入游戏。

(3)GateServer

GateServer主要负责在玩家登录时维护客户端与各服务器之间的网络连接与通讯,对各服务器和客户端的通信数据进行加解密、校验,过滤错误包,对客户端发来的一些协议作简单的逻辑处理,其中包括游戏逻辑中的一些超时判断。简而言之,就是对内分发消息,对外转发消息。

(4)GameServer

GameServer(GS)主要负责游戏逻辑处理。在软件架构层面,本系统将游戏的众多系统设计成GS 的子系统或模块,它们共同处理整个游戏世界逻辑的运算。游戏逻辑包括角色进入与退出游戏、跳GS 以及各种逻辑动作(比如行走、说话和攻击等)。由于整个游戏世界有许多游戏场景,在该架构中一组服务器有3 台GS 共同负责游戏逻辑处理,每台游戏服务器负责一部分地图的处理,这样不仅降低了单台服务器的负载,而且降低了GS 宕机带来的风险。

玩家角色信息里会保持玩家上次退出游戏时的地图编号和所在GS 编号,这样玩家再次登录时,会进入到上次退出时的GS。

(5)FightServer

与GameServer类似,也是游戏业务逻辑服务器,不同的是,FightServer只负责战斗方面的业务逻辑,战斗后将数据同步到GameServer及其他Server。这样做的好处时,业务分工明确,易维护管理,又很好了提高业务逻辑服务的性能,因为战斗本身是游戏中非常耗费性能的一部分,将其独立出来,即便战斗中GS宕机了,也不影响战斗的持续进行。

(6)MailServer

与GameServer类似,也是游戏业务逻辑服,不同的是,MailServer主要负责玩家间邮件收发及聊天等的处理。

(7)ChargeServer

ChargeServer是计费服务器,负责统计游戏中玩家的消费情况及营收情况,如设计需要,可能还会负责玩家一些信息的验证,非常重要。

(8)PlatformServer

PlatformServer是一个可选的平台交互服。如果需要与第三方平台交互,即玩家可以直接用第三方平台的信息来直接注册登录游戏,给玩家注册游戏提供方便快捷的途径,有利于提升玩家数量。

(9)LogServer

LogServer主要负责游戏日志的打印处理,相当对游戏的跟踪监控记录,以便能快速的解决游戏运维过程中出现的各种问题。

 

 

3.3 服务器交互的主要流程

下面给出服务器之间数据通讯的主要流程,这些流程将展现出各种服务器之间交互和协同工作的方式。

图2 创建角色信息流程

 

图2 的流程说明了,在选角色过程中,客户端会把携带游戏账号和SessionKey 的选角色协议发给GateServer,GateServer 做一些简单处理之后转发给GameServer,GameServer要验证SessionKey的合法性,验证通过之后,GameServer会从角色信息缓冲区里取出该账户的所有角色信息发给客户端。这个过程在客户端的表现是,当选择好服务器组之后,客户端会直接显示该账号下的所有角色,之后就可以选择角色进入游戏了。

 

图3 玩家进入游戏流程

图3 的流程说明了,在玩家选角色正式进入游戏时,客户端会把携带游戏账号、角色ID 和SessionKey 的登录协议发给GateServer,GateServer 做一些简单处理之后转发给GameServer。GameServer会验证SessionKey 的合法性,验证通过之后,GameServer 会把验证通过的结果发给客户端,同时客户端发获取角色数据的协议,这些角色数据是一个玩家所有的游戏数据,包括装备、技能等等。

 

图4 游戏逻辑数据转发流程

 

图4 的流程说明了,在玩家游戏过程,客户端把逻辑协议(包括走、说话、跑、使用技能等)发给GG,GG 完成加解密和简单逻辑处理之后转发给GS,GS 负责这些协议的主要逻辑处理。

 

3      协议说明

3.1 TCP/IP协议

本游戏通信采用TCP/IP协议,长连接的方式实现。

当网络通信时采用TCP协议时,在真正的读写操作之前,serverclient之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立是需要三次握手的,而释放则需要4次握手,所以说每个连接的建立都是需要资源消耗和时间消耗的。

TCP短连接:

clientserver发起连接请求,server接到请求,然后双方建立连接。clientserver发送消息,server回应client,然后一次读写就完成了,这时候双方的连接就关闭了。

短连接的优缺点:管理起来比较简单,存在的连接都是有用的连接,不需要额外的控制手段,不足的地方频繁的建立与关闭连接,相当的消耗资源。

TCP常连接:

clientserver发起连接,server接受client连接,双方建立连接。Clientserver完成一次读写之后,它们之间的连接并不会主动关闭,后续的读写操作会继续使用这个连接。

长连接的优缺点:建立的连接一直可用,减少了频繁建立关闭的连接的资源开消,不过服务端要每隔一定时间发送一些没用的数据包来检测连接的存活性,Clientserver之间的连接如果一直不关闭的话,会存在一个问题,随着客户端连接越来越多,server早晚有扛不住的时候,导致服务端的崩溃,因此,须采取一定的措施来避免此种情况的发生。

 

3.2数据报文

1)报文格式:协议头+数据长度+真实数据区

                           

                                         图5数据报文

 

协议头:长度规定28个字节,4个字节保存协议编号,4个字节保存用户ID8个字节保存sessionID,8个字节保存IP4个字节保存端号口

数据长度:采用4个字节保存报文数据的长度

数据区:不定长,保存报文的真实数据

报文需编解码、加解密、压缩解压缩。

      

       3.3 客户端与服务端的数据交互

       客户端与服务端的数据交互过程如下图所示:

                            


                                                    图6 C/S简单交互流程

 

3.4  数据类型占用字节说明

游戏中各数据占用字节数对应如下:

 

 

类型

长度(bit)

描述

byte

8

基本数据类型原长

char

16

基本数据类型原长

short

16

基本数据类型原长

int

32

基本数据类型原长

long

64

基本数据类型原长

float

32

基本数据类型原长

double

64

基本数据类型原长

String

32

字符串,采用4字节保存长度

List<Object>

32

集合采用4字节保存其长度

7数据类型字节

4  TCP协议产生的问题

基于TCP的通讯协议才有可能产生粘包和断包的情况,粘包和断包的产生有多种原因,处理好粘包和断包的问题是网络编程必然面对的情况,下面简单概括下Mina中的处理方案。

我们知道网络通讯过程实际是对二进制数据进行处理的过程,二进制数据是计算机认识的数据。对于接收到的二进制数据我们需要将其转换成我们所熟悉的数据格式,此过程称为解码(decode);对于所要发送的数据,我们需要转换为计算机所能处理的二进制数据,此过程称为编码(encode)。

                                                                                  

 

                     

                                                           8人机交互

 

Mina对数据的编解码提供了良好的支持,它提供了过滤器ProtocolCodecFilter支持编码和解码过程,可以查看包org.apache.mina.filter.codec下的代码。

TCP通信的粘包与断包:

粘包:即发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾,如图:

                                               

断包:即接收的数据有残缺,不完整,如图:

                                               

 

对粘包的处理相对比较简单,只需要依据数据包的格式进行数据流的分割即可;对于断包的处理我们需要将断包的数据保存起来,等待接收下次的数据进行拼接。

Mina中的断包处理:

1.取得断包数据,如果有断包数据,就和当前数据拼接。

2.进行数据解码操作。

3.将可以进行解码操作的数据解码完成后,如果还有数据,则将剩余数据存入session中,等待下次数据到来,从步骤1开始再次执行。

 

小作此文 ,欢迎有同样兴趣的人士一起交流学习。

 

0 0
原创粉丝点击