java - 如何处理服务器和客户端中不同的数据包?

标签 java networking multiplayer packet

在我计划制作的游戏服务器和客户端中,从长远来看,我必须处理很多数据包。我想知道如何处理我的不同数据包的最佳实践是什么。

我的数据包有效负载将以 PacketID 开头。

创建一个扩展 Packet 的单独类并处理其中的逻辑是个好主意吗?例如Packet001Login?从长远来看,这会给我带来很多类(class)。

制作一个巨大 switch 语句是否更好?我对此表示怀疑。

最好的方法是我没有想到的吗?

非常感谢任何建议。

最佳答案

如果您在服务器端确实有足够的计算时间,您应该研究一种为不同包类型创建原型(prototype)的技术。

为了说明这一点和想法,我给你一些类似于类描述的 UML

UML:

class PacketPrototype
+ PacketPrototype(PacketType)
+ addData(DataType, Bitlength, ...)
+ deserilize(Bitstream stream) : ReceivedPacket
+ serilizeThis() : ToSendPacket
+ getPacketType() : int

您还需要一个包含所有 PacketPrototype 的类,并决定每个 PacketPrototype 对象的类型,应使用哪个 Prototype 来反序列化数据。

你需要一个知道每个 PacketPrototype 的类,我称之为 PacketPrototypeHolder

class PacketPrototypeHolder
+ register(PacketPrototype)
+ getPrototypeForPacketType(int Type) : PacketPrototype

建立时间协议(protocol)如下

PacketEnemy00 = new PacketPrototype(0)
PacketEnemy00.addData(Types.Int, 5) // health
PacketEnemy00.addData(Types.String, 16) // name
...

这意味着类型 0 的数据包由 5 位长的 int 和最大长度为 16 个字符的字符串组成。

我们必须在设置后将 PacketPrototype 添加到我们的 PacketPrototypeHolder

PacketHolder.register(PacketEnemy00)

如果服务器或客户端收到我们读取的数据包类型,那么我们就会这样做 (您可以从Bitstream读取数据)

Type = Bitstream.readInt(5)
Prototype = PacketHolder.getPrototypeForPacketType(Type)

ReceivedPacket OfReceivedPacket = Prototype.deserilize(Bitstream)

// we need here a switch/if statement to determine how to handle the reading of the data
switch(Type)
{
  case 0: // PacketEnemy00

Prototype.deserilize 调用从数据流中读取数据并将其放入 ReceivedPacket 对象中,从那里您可以通过索引操作或命名访问来访问数据。

作为一个例子,我用索引来做

   int UnitHealth = OfReceivedPacket.getInt(/* index, we want the 1st int */0);
   string UnitName = OfReceivedPacket.getString(/* index, we want the 1st string */0);

   and so on...
   break;
   ...
}

因此,我有效地将 switch 语句从网络层内部移至应用程序/使用层。

要删除开关,您需要采用数据驱动的方法。但它在引擎中的实现比硬编码的方法更复杂。

关于java - 如何处理服务器和客户端中不同的数据包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17709666/

相关文章:

silverlight - 如何在Windows Phone(7.5)上制作网络游戏?

java - 处理谷歌日期字符串并递增它们

javafx 程序中的 java.lang.reflect.InitationTargetException

c++ - 多个客户端程序如何同时相互共享消息?

c++ - 使用重叠 IO 获取发件人的 IP 地址

python - Twisted/Amp 网络 : Respond to all clients, 不仅仅是一个发出请求的人

java - 是否可以在没有特定元素 ID 的文本框中输入文本

java - SweetAlert 盒子打不开

android - 如何同步两部或多部安卓手机的系统时钟?

javascript - 在线多人游戏中常见 "tick"怎么办?