• 回合制策略游戏

    • 游戏后台网络通讯
    • 游戏通信协议
    • 网络同步
  • TCP UDP
  • 心跳机制
      • 原理
      • 心跳检测步骤
      • 应用层发送心跳包的技术
      • 要关闭掉线的TCP连接
      • UDP与心跳
      • 心跳包和轮询的区别
      • 客户端如何快速感知自己掉线
      • HOW
    • 参考

回合制策略游戏

回合制策略游戏是策略游戏的一种子类型,所有的玩家轮流自己的回合,只有自己的回合,才能够进行操纵。早期的战略由于硬件运算能力有限,在考量游戏乐趣的情况下,多半采取这种型式。

主要分类
战棋类游戏
SLG:角色扮演因素较少,战斗以整体策略为主。
SRPG:角色扮演因素为主,战斗为回合制,通常己方人员较少,特别依靠培养系统铸造的强人。
半即时制
使用行动点数系统,行动点数基于角色行动需要而设定的耗时系统或者行动速度的差异。半即时回合制是按照人物角色的速度来决定行动的先后顺序,速度快的角色可能一个回合可以攻击多次,是回合制游戏的发展趋势。

游戏后台网络通讯

网络通信本身是非常复杂的事情,目前的开发环境已经提供了相对来讲简单得多的编程接口,但是网络程序还是需要处理很多的问题。
两种处理方式:一种是跟游戏服务器耦合带一起,游戏服务器既处理问落接入相关的逻辑,也处理游戏逻辑。一种是把网络通信部分剥离住来,向游戏服务器提供一种以消息为单位的、非阻塞的、有Qos能力的中间服务,游戏服务器看不到网络的细节。
我们选择第二种好处,是基于这样的考虑,首先简化了游戏服务器的处理逻辑,降低了编程的难度。更易于提升后台整体的处理性能,不同部分可以独立的优化,因为它可以不断的优化和在不同项目里面去继承的。
这是非常简单的一张示意图,我们会有一个界面,在客户端和服务器端给它不同的接口,会有不同的形式,看不到网络的问题,而且都是非阻塞的形式,面向消息的服务,类似于有保障的、可持续的服务。

游戏通信协议

协议分两大类:文本协议和二进制协议,这是两个非常典型的例子,一是UDP,非常高效。一是文本协议,都是文字。文本协议直观,版本兼容性好,但是效率低。其实对于游戏来讲,我们最好能够做到不同的版本都可以玩,不强调所有的客户端都去升级,这对运营商有非常强的周期,这对运营商来说有很大的挑战。版本兼容性问题其实是我们在通信协议的时候,都需要重点考虑的。二进制协议效率高,但是不直观,版本兼容性处理相对复杂。
Web相关的游戏根据与浏览器交互的方式可能采用文本协议,基于效率原因,C/S类型的游戏通常采用二进制协议。

游戏服务器是时钟消息和网络消息驱动的,大部分代码都是接受消息,或者接纳,其实有很多的解码、编码、代码占了相当大的比例。我们可以把协议做一个区分,就变成一个消息的协议描述,然后生成工具,然后得到网络协议处理代码。

从游戏来讲,所有的在线游戏通常使用数据库来存储用户数据。通常MMO使用关系型数据库来存储数据,后面主要针对MMO进行存储方式的讨论。会有两种方式:一种是把游戏的每一个数据对象的属性看成一个单独字段,遵循RDBMS的要求来设计数据库表和索引,尽量符合3NF。以MMO为例,有帐号表、角色基本信息表、物品表、装备表等等,这是一种方式。
还有一种方式更具体,角色的列表类数据尽量采用blob来存储而不是另一个表。原则是这些列表数据只被角色自身所拥有,就是这个玩家所拥有,其他玩家不会拥有个数据,它的生命周期跟玩家是一致的,不存在其他的交叉拥有情况,技能、物品、装备、任务、好友等等都属于这种情况。
优点是存储表结构简单,通常几张表就可以玩一个游戏,不超过10个。存取交互简单,角色登录或者推出时通常只需要存取一到二条记录。同一个角色的数据易于保持一致,易于多版本数据共存。我们把这些数据存到数据库的时候,会把编码存到数据库里面。所以在数据库里面做完的数据可能会不一样,不过不会影响,它会共存。
这种方式也会有缺点,数据维护工具、客服工具实现相对复杂,需要提供特殊的API来操作数据。如果手上工具是通用的,可能比以前要直白一点。某些类型的统计相对要麻烦一些,有些常用的数据,比如说角色的等级,在这方面可以用一些方式解决你的问题。
举个例子,在MMOG这块,存储角色的概要信息,包括名字、基本属性等,用于显示角色列表和防止重名。还有存储角色的详细信息,存储帐号的仓库信息,存储公会的信息。
新趋势的影响,就是Nosql数据库,性能高,存在好的开源实现,游戏的数据访问多为唯一键访问,很少复杂的Query,符合Nosql数据库的特点。后面在游戏应用上,可能也会涉及到。

网络同步

网络同步面临的主要问题:第一如何减少网络波动对同步的影响;第二如何减少外挂对同步的破坏。如果没有外挂,网络几大问题没有服务器去运行。这两个问题单独都好解决,但是在一起比较难解决。我们解决这两个问题,会遵循几个原则:第一网络条件好的玩家获得好的体验;第二网络条件差的玩家尽可能获得好一些的体验,但不能拖累其他玩家的体验;第三外挂不能在网络同步方面获得持续的好处。对外挂方面,玩一个游戏是一个人,或者说非人类不清楚,所以说外挂不能在网络同步获得持续的好处。
为了解决问题我们有一些基本方法:首先要探测玩家的网络质量;第二在玩家机器与服务器之间进行时钟同步;第三基于游戏特点,设计合理的同步机制。像竞技类的游戏,都是根据它的某些特点决定的,这是需要我们权衡考虑的。这里强调一点,在外挂获得好处,跟玩家体验时间做一个折中,你要保证外挂持续得到源源不断的好处,这样外挂就会上去。对于探测、时钟同步都需要控制好。

TCP / UDP

UDP:用户数据报协议:主要用在实时性要求比较高的以及对质量相对较弱的地方.但是面对现在高质量的线路不会容易丢包,除非是一些拥塞条件下,如流媒体;
TCP:传输控制协议:是面连接的那么运行环境必然要求其可靠性不可丢包,有良好的拥塞控制机制如 http ftp telnet等;

TCP UDP
发送 安全送达
接收与建立连接 是(三次握手)
数据大小 无限制
可靠性 可靠
速度 慢(三次握手才能完成连接)
应用 流媒体

“心跳”机制

1.原理

心跳机制是定时发送一个自定义的结构体(心跳包),让对方知道自己还活着,以确保链接的有效性的机制。

发包方:可以是客户端也可以是服务端,看哪边实现方便合理。一般是客户端

在TCP的机制里面,本身是存在有心跳包的机制的,也就是TCP的选项(SO_KEEPALIVE)。系统默认是设置的是2小时的心跳频率,探测次数为5次,如果要使用TCP的KeepAlive保活机制,需要手工开启KeepAlive功能并设置合理的KeepAlive参数。但是它检查不到机器断电、网线拔出、防火墙这些断线。而且逻辑层处理断线可能也不是那么好处理。一般,如果只是用于保活还是可以的。心跳包一般来说都是在逻辑层发送空的包来实现的。下一个定时器,在一定时间间隔下发送一个空包给客户端,然后客户端反馈一个同样的空包回来,服务器如果在一定时间内收不到客户端发送过来的反馈包,那就只有认定说掉线了。只需要send或者recv一下,如果结果为零,则为掉线。

TCP的KeepAlive保活的缺陷
TCP协议自身先天就有KeepAlive机制,因为开启KeepAlive功能需要消耗额外的宽带和流量,所以TCP协议层默认并不开启KeepAlive功能,另一方面,KeepAlive设置不合理时可能会 因为短暂的网络波动而断开健康的TCP连接.

TCP仍然需要心跳包
在长连接下,有可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持长连接,保活。在获知了断线之后,服务器逻辑可能需要做一些事情,比如断线后的数据清理,重新连接,这个自然是要由逻辑层根据需求去做了。总的来说,心跳包主要也就是用于长连接的保活和断线处理。一般的应用下,判定时间在30-40秒比较不错。如果实在要求高,那就在6-9秒。

   心跳机制的原理很简单:客户端每隔N秒向服务端发送一个心跳消息,服务端收到心跳消息后,回复同样的心跳消息给客户端。如果服务端或客户端在M秒(M>N)内都没有收到包括心跳消息在内的任何消息,即心跳超时,我们就认为目标TCP连接已经断开了。由于不同的应用程序对感知TCP掉线的灵敏度不一样,所以,N和M的值就可以设定的不一样。灵敏度要求越高,N和M就要越小;灵敏度要求越低,N和M就可以越大。而要求灵敏度越高,也是有代价的,那就是需要更频繁地发送心跳消息,如果有几千个连接同时频繁地发送心跳消息,那么其所消耗的资源也是不能忽略的。当然,网络环境(如延迟的大小)的好坏,也对会对N和M的值的设定产生影响,比如,网络延迟较大,那么N与M之间的差值也应该越大(比如,M是N的3倍)。否则,可能会产生误判 -- 即TCP连接没有断开,只是因为网络延迟大才及时没收到心跳消息,我们却认为连接已经断开了。

2.心跳检测步骤

1.客户端每隔一个时间间隔发生一个探测包给服务器
2.客户端发包时启动一个超时定时器
3.服务器端接收到检测包,应该回应一个包
4.如果客户机收到服务器的应答包,则说明服务器正常,删除超时定时器
5.如果客户端的超时定时器超时,依然没有收到应答包,则说明服务器挂了

3.应用层发送心跳包的技术

由应用程序自己发送心跳包来检测连接是否正常,大致的方法是:
服务器在一个Timer事件中定时向客户端发送一个短小精悍的数据包,然后启动一个低级别的线程,在该线程中不断检测客户端的回应,如果在一定时间内没有收到客户端的回应,即认为客户端已经掉线;同样,如果客户端在一定时间内没有收到服务器的心跳包,则认为连接不可用。
缺陷:代码较多,稍显复杂

4.要关闭掉线的TCP连接

无论是普通掉线(立即感知)还是心跳超时掉线(非立即感知),都需要关闭对应的TCP连接以释放系统资源。

5.UDP与"心跳"

由于UDP是无连接的协议,所以,当使用UDP引擎时,几乎肯定是需要配备心跳机制的,使用心跳消息确认客户端还在线,以保证服务端不会过早释放对应的Session或长期保留已失效的Session.

心跳包和轮询的区别

心跳包和轮询看起来类似, 都是客户端主动联系服务器, 但是区别很大:

轮询是为了获取数据, 而心跳是为了保活TCP连接。
轮询得越频繁, 获取数据就越及时, 心跳的频繁与否和数据是否及时没有直接关系
轮询比心跳能耗更高, 因为一次轮询需要经过TCP三次握手, 四次挥手, 单次心跳不需要建立和拆除TCP连接.

客户端如何快速感知自己掉线?

在某些客户端电脑上,比如拔掉网线,或断开wifi,程序可能需要几秒到几分钟才能感知到自己掉线,不同的电脑这个感受的时间不一样。那么如何才能让客户端尽可能快地得到掉线通知了?
可以利用socket写超时的机制,像下面这样做:
(1)将Socket发送缓冲区的大小设置为0。 对应IRapidPassiveEngine的Advanced属性的SocketSendBuffSize属性。
(2)设置写超时为一个较小的值,如30秒。 对应IRapidPassiveEngine的Advanced属性的WriteTimeoutInSecs属性。
这样,结合上面的心跳发送机制(如每隔5秒发送一个心跳),则当网络断开后,在发送心跳消息,最多再过30秒,程序就会得到掉线通知了。

HOW

应用层心跳的确是检测连接有效性,双方是否存活的最佳实践,那么剩下的问题就是怎么实现。

最简单粗暴做法当然是定时心跳,如每隔 30 秒心跳一次,15 秒内没有收到心跳回包则认为当前连接已失效,断开连接并进行重连。这种做法最直接,实现也简单。唯一的问题是比较耗电和耗流量。以一个协议包 5 个字节计算,一天收发 2880 个心跳包,一个月就是 5 * 2 * 2880 * 30 = 0.8 M 的流量,如果手机上多装几个 IM 软件,每个月光心跳就好几兆流量没了,更不用说频繁的心跳带来的电量损耗。

既然频繁心跳会带来耗电和耗流量的弊端,改进的方向自然是减少心跳频率,但也不能过于影响连接检测的实时性。基于这个需求,一般可以将心跳间隔根据程序状态进行调整,当程序在后台时(这里主要考虑安卓),尽量拉长心跳间隔,5 分钟,甚至 10 分钟都可以。而当 App 在前台时则按照原来规则操作。连接可靠性的判断也可以放宽,避免一次心跳超时就认为连接无效的情况,使用错误积累,只在心跳超时 n 次后才判定当前连接不可用。当然还有一些小 trick 比如从收到的最后一个指令包进行心跳包周期计时而不是固定时间,这样也能够一定程度减少心跳次数。

参考:

棋牌游戏服务器的架构设计需要注意哪些点 2017-04
TCP/UDP区别&&心跳包机制,2017-05
心跳机制,2014-07
请教用NIO框架MINA开发IM时的心跳和会话超时问题,2016-12
移动 IM 开发之心跳,2016-04
HTML5 QQ斗地主诞生记,无线游戏产品部

回合制游戏网络通信协议及心跳机制调研相关推荐

  1. 计算机4个数字游戏怎么玩,网络回合制游戏怎么玩 神武4电脑版属于回合制吗

    在那个用电脑玩网游的年代,网络回合制网游一直是不可或缺的重要组成部分,回合制这一模式来源于桌面游戏,电脑游戏的雏形即来自于此.回合制网络游戏节奏较慢,玩家可以有大把的时间用来聊天:回合制游戏操作简单, ...

  2. 今天开始做战斗,回合制战斗代码实现第一篇补充,从头开始,简单的2d回合制游戏一些文档方面的知识

    上一篇代码贴完了,总是感觉缺少些东西,因为光看代码用时候不是很直观,我们还是需要些文档来辅助理解.好了,所以补充些内容. 2009 年 8 月,<梦幻西游>同时最高在线人数达到 256 万 ...

  3. 对回合制游戏的探讨以及想法

    回合制作为游戏的一大类型最早火于<勇者斗恶龙>,该游戏作为经典的回合制拥         有着庞大的故事观和职业系统,玩家通过回合制的方式进行体验游戏,获取并推动者剧     情,在某个层 ...

  4. 今天开始做战斗,回合制战斗代码实现第一篇,从头开始,简单的2d回合制游戏

    拖了这么久,终于弄到战斗系统了,不过仙剑demo的回合制战斗比较复杂,所以我们从最简单的2d回合制游戏战斗开始讨论,看看游戏战斗系统代码什么样子. 还记得回合制战斗的流程图吗,UI的时候我曾经贴过,, ...

  5. 一个简单的Visual C++回合制游戏,完整源码展示

    Visual+C++编写的一个回合制游戏演示源码,源码编译环境为vs2010,希望能和大家一起交流,共同学习,共同进步.请注意,要运行生成的EXE文件,请先将EXE文件从Debug目录中拷出来,放到上 ...

  6. C#实现回合制游戏模拟

    文章开始把我喜欢的这句话送个大家:这个世界上还有什么比自己写的代码运行在一亿人的电脑上更酷的事情吗,如果有那就是让这个数字再扩大十倍!!! 底部有下载链接:附带代码.答辩PPT.数据.音乐等素材. 规 ...

  7. 2D回合制游戏开发相关

    是时候填这个坑了.-----2020年4月28日 17点28分 我又来了,是时候有个结果了.也算是为了儿时的梦想吧,我想要的真不多. ----2020年11月9日16点24分 我又来更新了,哈哈哈.- ...

  8. php 开发回合游戏,Unity回合制游戏战斗模块的制作

    回合制游戏相信大家没玩过也见过,了解它的玩法.回合制,那就是你来我回的,你一回合我一回合,直到把对方打败.市面上的回合制游戏比较经典的有梦幻西游,问道,神武,完美世界.这几个都还是很不错的.回到正题, ...

  9. php做异步回合制,请问有哪些游戏属于半回合制游戏?

    其实没有很确定的"半回合制" 最不回合制的肯定是动作游戏,然后从动作游戏到 纯回合制,有这么几种机制: 一, 大回合制,高级战争之类的战棋游戏是这种机制.一方所有单位行动完了,另一 ...

最新文章

  1. 解决在onCreate()过程中获取View的width和Height为0的4种方法
  2. 五大常用算法之二:动态规划算法
  3. gis 空间分析 鸟类栖息地选取_动物栖息地选择评估的常用统计方法
  4. 使用network管理DD恢复全库操作步骤
  5. 商业实战第三场 电视直销好记星
  6. 详解Java中的注解
  7. IDEA去除掉虚线,波浪线,和下划线实线的方法
  8. UVA11870 Antonyms【并查集】
  9. 免费python全套教程-0基础学python 全套教程送你参考
  10. BlockingQueue接口分析
  11. 微信小程序毕业设计和毕业论文怎么写,答辩流程是怎样的?
  12. android sony 镜像,解释如何使用Sony TV DLNA屏幕镜像功能
  13. 如何根据身份证号码辨别性别
  14. 快递100商家下单demo
  15. 数组和链表的顺序遍历的时间比较
  16. 编码分布式矩阵乘法(Coded Distributed Matrix Multiplication, CDMM)问题简单介绍
  17. ifstat网络流量监控之/proc/net/dev文件
  18. 自建免费的代理ip池
  19. 将镜像刻录到U盘的方法
  20. 协方差Cov(X,Y)的含义(转)

热门文章

  1. 阿里18岁,因为相信而看见——阿里巴巴年会全记录
  2. 手机里刷屏海报文案怎么写?(下)
  3. CCNA认证简介之资料篇
  4. 北邮学生考试挂科,毕业没有学位证,错失百度京东offer
  5. debug时idea控制台不显示日志怎么办
  6. Windows Binaries for Python Extension Packages
  7. java达达租车接口_java达达租车系统,初学者,希望大家能给些批评建议,共同学习...
  8. Google App Engine的申请方法
  9. 揭秘信用卡账单、支付宝背后的黑色产业链
  10. 高可用实践之统一鉴权(三)