一个大型的网落游戏服务器应该包含几个模块:网络通讯,业务逻辑,数据存储,守护监控(不是必须)。其中业务逻辑可能根据具体需要,又划分为好几个子模块。
这里说的模块可以指一个进程,或者一个线程方式存在,本质上就是一些类的封装。
对于服务器的并发性,要么采用单进程多线程,要么采用多进程单线程的方式,说说两种方式的优缺点:
网络通讯层,业务逻辑,数据存储,分别在独立的线程中,无守护进程。
优点:
缺点:
网路通讯,业务逻辑,数据存储,守护进程,分别在不同的进程。
优点:
缺点:
下面先按照一个游戏的功能,将服务器的功能分块框架画出来:
点击图片可放大
以上是一个游戏服务器最基础的功能框架图,接下来要做的就是设计服务器的框架了
Client<->GameServer<->DB
所有业务数据集中处理
优点:
简单,快速开发
缺点:
GameServe1
Client | DB
GameServer2
玩家不断增多->分线->程序自动或玩家手动选择进入 **缺点:**运营到后期,随着每条线玩家的减少, 互动大大减少。
按地图划分服务器,当前主流 新手村问题:《天龙八部》提出了较好的解决方案,建立多个平行的新手村地图,一主多副,开服时尽可能多的同时容纳新用户的涌入,高等级玩家从其它地图回新手村只能到达主新手村。
注:在GateServer和CenterServer之间是有一条TCP连接的。而GameServer和LogServer之间的连接可以是UDP连接。这是有一个大概的图,很多地方需要细化。 **GateServer:**网关服务器,AgentServer、ProxyServer
优点:
缺点:
解决:
改进:
将网关服务器细化为LogingateServer和多个GameGateServer.
由于网络游戏存在很多的业务,如聊天,战斗,行走,NPC等,可以将某些业务分到单独的服务器上。这样每个服务器的程序则会精简很多。而且一些大流量业务的分离,可以有效的提高游戏服务器人数上限。
优点:
改进: 甚至可以将登陆服务器细化拆分建角色,选择角色服务器
下图中每个方框表示一个独立的进程APP组件,每个服务进程如果发生宕机会影响部分用户,整体服务但不会全部中断。在宕机进程重启后,又可以并入整体,全部服务得以继续。
在这个架构里面,**GameServer实际上是一个游戏逻辑的综合体,**里面可以再去扩展成几个不同的逻辑服务器,通过PublicServer进行公共数据交换。
UserServer实际上扮演了一个ServerGroup的领头羊的角色,它负责向LoginServer注册和更新服务器组的信息(名字,当前人数),并且对Agent进 行调度,对选择了该组的玩家提供一个用户量最少的Agent。同时,它也兼了一个角色管理服务器的功能,发送给客户端当前的角色列表,角色的创建,删除, 选择等管理操作,都是在这里进行的。而且,它还是一个用户信息的验证服务器,GameServer需要通过它来进行客户端的合法性验证,以及获取玩家选择 的角色数据信息。 采用这种架构的游戏,通常有以下表现:
根据游戏类型 实时性要求/是否允许丢包 来决定 TCP/UDP协议
TCP每次发送一个数据包后都要等待接收方发送一个应答信息,这样TCP才可以确认数据包通过因特网完整地送到了接收方。如果在一段时间内TCP没有收到 接收方的应答,他就会停止发送新的数据包,转而去重新发送没有收到应答2的数据包,并且持续这种发送状态知道收到接收方的应答。所以这会造成网络数据传输 的延迟,若网络情况不好,发送方会等待相当长一段时间 UDP:无连接,不可靠,不保证顺序,快
长连接,指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接,一般需要自己做在线维 连接→数据传输→保持连接(心跳)→数据传输→保持连接(心跳)→……→关闭连接 **短连接,**是指通信双方有数据交互时,就建立一个TCP连接,数据发送完成后,则断开此TCP连接,如Http 连接→数据传输→关闭连接
Unix5中io模型
IO分两个阶段:
根据这2点IO类型可以分成:
同时阻塞多个I/O操作。而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写时,才真正调用I/O操作函数
Java#Selector 允许套接口进行信号驱动I/O,并安装一个信号处理函数,进程继续运行并不阻塞**。当数据准备好时**,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据.
Java#NIO2 发出系统调用后,直接返回。通知IO操作完成。 前四种同步IO,最后一种异步IO.二者区别:第二个阶段必须要求进程主动调用recvfrom.而异步io则将io操作全部交给内核完成,完成后发信号通知。此期间,用户不需要去检查IO操作的状态,也不需要主动的去拷贝数据。
同步/异步关注的是消息如何通知的机制。而阻塞和非阻塞关注的是处理消息。是两组完全不同的概念。
Select Poll
Epoll(Linux) Kqueue(FreeBSD)
IOCP Windows
Reactor Dispatcher(分 发器),Notifer(通知器), 事件到来时,使用Dispatcher(分发器)对Handler进行分派,这个Dispatcher要对所有注册的Handler进行维护。同时,有一 个Demultiplexer(分拣器)对多路的同步事件进行分拣。
Proactor Proactor和Reactor都是并发编程中的设计模式.用于派发/分离IO操作事件的。这里所谓的IO事件也就是诸如read/write的IO操作。"派发/分离"就是将单独的IO事件通知到上层模块。两个模式不同的地方在于,Proactor用于异步IO,而Reactor用于同步IO。
两个模式的相同点,都是对某个IO事件的事件通知(即告诉某个模块,这个IO操作可以进行或已经完成)。在结构上,两者也有相同点:demultiplexor负责提交IO操作(异步)、查询设备是否可操作(同步),然后当条件满足时,就回调handler。 不同点在于,异步情况下(Proactor),当回调handler时,表示IO操作已经完成;同步情况下(Reactor),回调handler时,表示IO设备可以进行某个操作(can read or can write),handler这个时候开始提交操作。
TCP Server框架: Apache MINA(Multipurpose Infrastructure for Network Applications)2.0.4 Netty 3.5.0Final Grizzly 2.2 Quickserver是一个免费的开源Java库,用于快速创建健壮的多线程、多客户端TCP服务器应用程序。使用QuickServer,用户可以只集中处理应用程序的逻辑/协议 **Cindy :**强壮,可扩展,高效的异步I/O框架 **xSocket:**一个轻量级的基于nio的服务器框架用于开发高性能、可扩展、多线程的服务器。该框架封装了线程处理、异步读/写等方面 ACE 6.1.0 C++ADAPTIVE CommunicationEnvironment, **SmaxFoxServer 2.X :**专门为Adobe Flash设计的跨平台socket服务器
AMF/JSON/XML/自定义/ProtocolBuffer
无论是做何种网络应用,必须要解决的问题之一就是应用层从字节流中拆分出消息的问题,也就是对于 TCP 这种字节流协议,接收方应用层能够从字节流中识别发送方传输的消息.
len | message_id | data
|separator | header | body |
| len | message_id | data
TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。
解决措施:
对于发送方引起的粘包现象,用户可通过编程设置来避免,TCP提供了强制数据立即传送的操作指令push,TCP软件接收到该操作指令后,就立即将本段数据发送出去,而不必等待发送缓冲区满; TCP-NO-DELAY-关闭了优化算法,不推荐
对于接收方引起的粘包,则可通过优化程序设计、精简接收进程工作量、提高接收进程优先级等措施,使其及时接收数据,从而尽量避免出现粘包现象-当发送频率高时依然可能出现粘包
接收方控制,将一包数据按结构字段,人为控制分多次接收,然后合并,通过这种手段来避免粘包。-效率低
接收方创建一预处理线程,对接收到的数据包进行预处理,将粘连的包分开
基本思路是首先将待处理的接收数据(长度设为m)强行转换成预定的结构数据形式,并从中取出数据结构长度字段,即n,而后根据n计算得到第一包数据长度
1) 若n<m,则表明数据流包含多包数据,从其头部截取n个字节存入临时缓冲区,剩余部分数据一次继续循环处理,直至结束。
2) 若n=m,则表明数据流内容恰好是一完整结构数据,直接将其存入临时缓冲区即可。
3) 若n>m,则表明数据流内容尚不够构成一个完整结构数据,需留待与下一包数据合并后再行处理。
寻路的问题在于自然的移动,追着一个单位打,或者进入射程中停下来,比起如何自然的经过一个单位打,成为了一个,为什么你要在A站或者B站坐公交的问题,Why,如何才能符合逻辑的设计---敌人进攻的单位,这个AI,不但是策略的问题,还是行为的问题,所以,将敌人的最终目标确定在哪里呢?
回答:AI 和 行为控制模块要分成两个模块来做
这必须是一个独立的模块,可以避免为每个单位都写逻辑的同时,让大部分单位战斗起来有个统一的目的;这么做的好处是,大部分的CPU时间都在一段高效率的代码上,由这个模块负责按照顺序给每个单位下达动作指令
如果有必要 还需要一个监控模块,监控单位的状态改变
就是上面写过的 Why , 我要在A站乘车 还是B站乘车的逻辑,我是优先攻击单位,还是优先攻击建筑物的逻辑。。。本虎还没想明白,这是一个逻辑怪圈。。。。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。