通过..编程客户端/服务器通信?(JAVA)



我有一个关于在网络游戏中编程客户端/服务器通信的一般问题。我使用TCP作为协议,并且通信。。。有效,但我不确定这是否是一种有效的方法。

一般来说,客户端上发生的操作将经历以下所有步骤:

  1. 一些动作(如投火球)
  2. [*]对于这个动作,我定义了一个字符串(例如#F#270#130#,这意味着"F"表示它是一个火球,270是(例如)角度的度数,130-发射火球的速度。)
  3. 字符串进入Client&等待队列
  4. 字符串已发送
  5. 字符串由服务器接收
  6. [*]Server需要一个能够检测字符串含义的行解释器(这里:F的意思是什么?它是一个火球!)&添加一个唯一标识,该标识基于接收命令的客户端
  7. [*]服务器需要根据发生的动作计算逻辑(火球会对某人造成伤害,是(立即)击中某人还是先飞?)
  8. 服务器向所有客户端发送一个(更新的)操作字符串。(例如,也许由于某种原因火球的速度减慢了——这里会有一个更新的字符串(#F#1234#270#90#-12345是唯一的玩家身份)
  9. 客户端接收字符串
  10. [*]客户端将字符串解析为命令+处理它(激发动画序列…)
  11. 最初发送命令的客户端将接收到的字符串与waitingqueue中的字符串进行比较-如果相等,则不执行任何操作(以平滑某些操作,否则由于连接问题/延迟,某些操作将发生两次或从一个位置跳到另一个位置,基于ping

真的有必要经历所有这些步骤吗?在所有标有[*]的步骤中,我需要为每个命令定义新的行解释器/action,所以我对每个操作编码两次,client&服务器端。我读过一些关于发送可序列化对象的文章,但总的来说,这个想法对我来说似乎是一样的,我发送一个对象,它必须被解释+处理,然后我发回一个对象。。。

有什么提示吗?要解决整个通信更优雅,用更少的编码?或者有点排序——所有这些不同动作的#F##M##H#标签都让它变得越来越复杂:)

(事实上,我实际上有以下处理程序/操作:

-移动-查看/旋转-hpchange-火焰箭头-生成/断开连接…)

希望你能理解我的意思——我知道,我可以继续这样编码,它会以某种方式工作,但它看起来太复杂了

谢谢!

如果您:

  1. 定义一个名为Action或类似的对象,它具有以上所有参数——动作类型、动作方向(或目标)、造成的伤害等
  2. 在游戏正常执行时创建这些Action对象
  3. 使用链接到TPC套接字的ObjectOutputStream将整个Action对象输出到服务器/将其传递回客户端
  4. 在服务器上,通过检查从ObjectInputStream接收的对象来解释发生了什么

我认为,如果您添加更多的逻辑,而不仅仅是分析字符串,但不是那么快(因为进入ObjectOutputStream的对象需要序列化),这种方式会更干净、更灵活。

在决定游戏是否需要更改之前,您需要考虑几个因素。

首先,TCP是最好的通信信道吗?你把它比作UDP了吗。使用UDP实现联网会更好吗?如果少了几个包裹会有关系吗?如果网络速度慢,会发生什么?

其次,查看轮询/推送到服务器的频率。这能减少吗?游戏必须是实时的吗。游戏的所有部分都必须是实时的吗。也许某些事情可能是非实时的。火球会沿着直线继续,所以你不必不断更新服务器的位置,你可以告诉它它的方向和速度。游戏的其他方面可以是非实时的。唯一需要发送的是玩家的位置和行动。像冲突检测这样的大多数其他事情都可以卸载到客户端。

第三,是否每个按键都需要发送到服务器?如果用户靠墙并想进一步移动,客户端知道他们不能,因此不会将这些按键发送到服务器。如果用户已移动到新的有效位置,则更新服务器。某些东西可以一次性缓冲并发送到服务器,而不是向服务器发送几个查询吗。即,如果我向前移动,跳跃并投掷火球,即客户端上的3个按键,它们能否在下一个500毫秒被缓冲和发送?

如果你担心网络开销,你应该在比特级别工作。与其发送11字节长的长字符串"#F#270#130#",不如发送3个连续字节(24位)。

7位表示动作(127个不同的动作)。9位表示角度(1-512),但您只需要0-360度。8位表示力。

这种或任何其他字节格式更短,更容易在网络上使用,并生成更紧凑的代码。此外,二进制比较更快,因此在服务器上编写动作解析器现在变得更容易了。也就是说,你只需查看前7位,并将其与内部进行比较,而不是用一个大的交换机来查找#F#

你能减少其他网络开销吗,而不是由客户端决定,服务器能决定吗。即标准力或2级力(因为这可以用1位来表示要好得多)。这阻止了客户端和恶意用户向服务器发送垃圾数据(比如999的强制),现在强制可以是0或1,即速度为10或20,没有什么愚蠢的。

最新更新