忽略响应能力。在局域网上,ping无关紧要。在互联网上,往返60-100毫秒是一种祝福。向落后的上帝祈祷,您不会获得超过3K的峰值。您的软件必须以非常低的每秒更新数运行,这是一个问题。如果您每秒拍摄25次更新,那么在收到数据包并对其执行操作之前,您将有40ms的最大时间间隔。那就是单线程的情况...
设计系统的灵活性和正确性。这是我关于如何将网络子系统挂接到游戏代码中的想法:消息传递。解决许多问题的方法可以是“消息传递”。我认为消息传递可以治愈实验室老鼠的癌症。信息为我节省了200美元或更多的汽车保险。但是,认真的说,消息传递可能是将任何子系统连接到游戏代码的最佳方法,同时仍保持两个独立的子系统。
对于网络子系统和游戏引擎之间的任何通信,以及任何两个子系统之间的通信,请使用消息传递。子系统间消息传递可以很简单,就像使用std :: list的指针传递的数据块一样。
只需有一个传出消息队列和对网络子系统中游戏引擎的引用。游戏可以将想要发送的消息转储到传出队列中,并自动将它们发送出去,或者在调用“ flushMessages()”之类的函数时也可以。如果游戏引擎有一个较大的共享消息队列,那么所有需要发送消息的子系统(逻辑,AI,物理,网络等)都可以将消息转储到其中,然后主游戏循环可以读取所有消息然后采取相应行动。
我会说,在另一个线程上运行套接字是可以的,尽管不是必需的。这种设计的唯一问题是,它通常是异步的(您不确切地知道何时发送数据包),这会使调试变得困难,并使与时序相关的问题随机出现/消失。尽管如此,如果做得正确,这些都不是问题。
从更高的层次上讲,我想说的是独立于游戏引擎的网络。游戏引擎不在乎套接字或缓冲区,而在乎事件。事件包括诸如“玩家X开枪”,“在游戏T发生爆炸”之类的事情。这些可以由游戏引擎直接解释。它们从何处生成(脚本,客户的动作,AI播放器等)都无关紧要。
如果将网络子系统视为发送/接收事件的一种方式,那么与仅在套接字上调用recv()相比,您将获得许多好处。
您可以优化带宽,例如,采用50条小消息(长度为1-32字节),然后让网络子系统将它们打包为一个大数据包并发送。也许这可以在发送之前先压缩它们。另一方面,代码可以将大数据包再次解压缩/解包为50个离散事件,以供游戏引擎读取。这一切都可以透明地发生。
其他很酷的功能包括单人游戏模式,该模式通过在同一台计算机上运行纯客户端+纯服务器,通过共享内存空间中的消息传递进行通信,从而重用网络代码。然后,如果您的单人游戏正常运行,则远程客户端(即真正的多人游戏)也将运行。此外,它会迫使您提前考虑客户端需要哪些数据,因为您的单人游戏看起来要么正确,要么完全错误。混合搭配,运行服务器并在多人游戏中成为客户端-一切都一样容易。