我试图了解服务器-客户端网络如何为实时多人游戏工作。
假设我正在构建一个实时多人游戏,比如FPS。
如果玩家A向玩家B开枪,后端< code >服务器需要告诉玩家B他们被击中了。
我知道如何让玩家 A 告诉后端服务器他开了一枪,只是向服务器发送请求,但是如何让后端
服务器
告诉玩家 B
他们被枪杀了?
玩家B是否必须每0.1秒检查一次后端server
以查看是否发生了什么事情,或者是否有更有效的方法?
从服务器获取数据的 2 种方法如下:
1)同步方法(或轮询方法) - 这就是您所描述的 - 检查每个间隔的更新。
2) 异步方法(或推送方法)-对于您描述的用例更有效-客户端订阅一次更新,服务器在收到更新时通知客户端。例如,您可以使用websockets来实现它。如果您没有绑定到http
-only层,则可以使用ZeroMQ
来实现它。
让我们向前跳几个月。你的游戏有几百万下载量,你的服务器
部分必须应付一大群24/7/365在线的敏锐游戏玩家。
这种景观将有助于显示分布式系统设计属性的核心重要性,以及任何低延迟控制软件(这种情况下,游戏毫无疑问)将面临的难题。
为什么延迟?一个好的游戏设计努力创造和维护逼真的用户体验。让我们举一个射击的例子——如果玩家 A 在最后几分钟内摧毁了目标 X,然后瞄准了 Y,最后瞄准了 Z,但玩家 C 甚至在玩家 A 开始射击之前就射杀了玩家 A,而由于端到端游戏连接延迟的延迟差(不相等),来自 C 的“子弹”“迟到”到达服务器
并“在”目标 X 之后“分发, Y 和 Z 被确认被摧毁 - 你会杀死 A 并重生 X、Y、Z 还是让 X、Y、Z 爆炸并让 A 稍后死去,在没有警告的情况下在蓝天下死去,或者你会让他/她继续前进,就好像没有被玩家 C 杀死一样?- 您的平台游戏体验将变得非常不公平,而不仅仅是涉及的玩家之一C,X,Y,Z。用户讨厌这个。火焰会很快随之而来。
时间上的延迟可变性(延迟抖动)是另一个问题——一些著名的平台,IL2-斯图莫维克就是这样的例子,由于这种未处理的延迟相关的分布式游戏引擎控制,经历了游戏中对象的“跳跃”。游戏社区很快意识到了这一缺陷,黑MOD产生了许多MOD,这一弱点被用来为(欺骗)玩家带来不公平的利益,他们从阻止数据包中受益,分发游戏中的现实更新,并使用这种黑客技术,他们的飞机变得隐形(无法被攻击者的子弹击中),有时甚至在3D场景中出现UFO,因为一些飞机的游戏中3D坐标更新很晚/很晚才到达。
如果你意识到,< code>0.1秒是关于游戏中的现实更新不超过< code>10 FPS,而当代游戏中的现实努力达到大约50 - 80 - 120 FPS以获得高保真的用户体验,你将面临更大的痛苦。
ZeroMQ
是分布式系统的一个奇妙框架。掌握这个工具无疑会帮助你了解很多关于非阻塞的知识,关于高效的端到端消息传递(任何类型的更新、控制、信令),你还将学习如何减少流量(想象10个游戏玩家对1.000个游戏玩家对100.000个游戏玩家的网络段负载)。
ZeroMQ
还将帮助您在多台服务器端机器之间包括工作负载平衡,从而随着玩家数量的增加而增加您的后端能力-ZeroMQ
支持几乎线性可扩展性,这值得在学习曲线中付出一些痛苦,不是吗?
服务器端通常有许多职责需要同时处理。游戏内分布式消息传递框架事件处理引擎的过度简化的核心循环如下所示:
... # setup
while True: # ||||||||||||||||||||||| DANGER-ZONE vvvvvvvvvvvvvvv FAST
anInterruptSegmentedCDOWN = 60 * 100 # 100 * 10[ms] dual-poll-overhead -> aMinuteCOUNTER
#-----------------------------------------------------------
while anInterruptSegmentedCDOWN > 0: # CDOWN-loop-[aMinuteCOUNTER ~ 1 minute with 6000-loops 10 [ms] each ]-----------100x [sec] 6000x [min]
anInterruptSegmentedCDOWN -= 1
#-------------------------------# SIGsPORT >>> AVOID WARM-UP delay at the end of the story, where SIG_EXIT needs to be delivered IMMEDIATELY >>> https://stackoverflow.com/a/33435244/3666197
try: #----------.send()--------# NOBLOCK-# .send() aMSG, may throw an EXC
...
except:
...
finally:
...
#-------------------------------# CtrlPORT
if ( 0 != aCtrlSOCKET.poll( 0 ) ): # IF .poll( 1 ) - a fast .poll()
...
#-------------------------------# RecvPORT
if ( 0 == aRecvSOCKET.poll( 9 ) ): # IF !.poll( 9 ) - relax & wait for aMsg ... 10 [ms] REDUCED waiting, due to a need to keep a SIGsPORT heart-beat about 100 ms so as to avoid IDLE/WarmUp on socket once SIG_EXIT is to be delivered
...
else: # ELSE = [MSG] IS HERE,
# GO GET THE JOB DONE ~~~~~~~ AI-ZONE <<<< [MSG]
... # ~~~~~~~ HERE
# # THE MAGICS
# # HAPPEN
continue
# |||||||||||||||||||||||||||||||||||||||||| DANGER-ZONE ^^^^^^^^^^^^^^^ FAST
您可能对更多细节感兴趣——WebSocket和ZeroMQ
之间有什么区别
然而,对于您的进一步问题,您可能希望看到关于此主题的更大图片
现在我的ServerSocket是这样的 一切正常,客户端连接,发送一些数据,服务器读取它,但我的问题是如何从我的服务器发送消息到所有的客户端?我目前保存客户端上的ArrayList,所以我可以只是循环,ArrayList打开一个作家和刷新它,但我想发送的数据,我得到我的ClientConnection类 我应该如何处理这个代码?在服务器类上完成的所有操作?或
前面的章节介绍了所有 Redis 的重要功能组件: 数据结构、数据类型、事务、Lua 环境、事件处理、数据库、持久化, 等等, 但是我们还没有对 Redis 服务器本身做任何介绍。 不过, 服务器本身并没有多少需要介绍的新东西, 因为服务器除了维持服务器状态之外, 最重要的就是将前面介绍过的各个功能模块组合起来, 而这些功能模块在前面的章节里已经介绍过了, 所以本章将焦点放在服务器的初始化过程,
我有这个代码可以在eclipse中与android Studio中的客户端通信服务器,我使用套接字,客户端向服务器发送消息,服务器读取该消息并确定一切正常,但当服务器向客户端发送消息时,客户端不强制任何东西;这是代码 还有这个 此代码是服务器代码的一部分,如果您需要客户端代码(Android Studio),请告诉我。 我需要帮助拜托
我想在一些计算机之间建立点对点连接,这样用户就可以在没有外部服务器的情况下聊天和交换文件。我最初的想法如下: 我在服务器上制作了一个中央服务器插座,所有应用程序都可以连接到该插座。此ServerSocket跟踪已连接的套接字(客户端),并将新连接的客户端的IP和端口提供给所有其他客户端。每个客户端都会创建一个新的ServerSocket,所有客户端都可以连接到它。 换句话说:每个客户端都有一个Se
本文向大家介绍python服务器与android客户端socket通信实例,包括了python服务器与android客户端socket通信实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了python服务器与android客户端socket通信的方法。分享给大家供大家参考。具体实现方法如下: 首先,服务器端使用python完成,下面为python代码: 下面是Android代码: 安卓代
本文向大家介绍java UDP通信客户端与服务器端实例分析,包括了java UDP通信客户端与服务器端实例分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了java UDP通信客户端与服务器端。分享给大家供大家参考,具体如下: 最初Udp是以字节为单位进行传输的,所以有很大的限制 服务器端: 用户端: 注:由于必须以字节为单位进行传输,Udp的传输用了一个容器类的东西,用来接收字节 先建