通用包系统的Lidgren

本文关键字:Lidgren 系统 包系统 | 更新日期: 2023-09-27 18:16:10

我用的是Lidgren。在客户机/服务器体系结构中,在服务器和客户机之间发送数据的网络。我已经创建了一个Packet类,用于在网络上发送数据包。

Packet.cs

public abstract class Packet : IPackable
{
    public abstract void PackIntoNetMessage(NetOutgoingMessage msg);
    public abstract void PopulateFromNetMessage(NetIncomingMessage msg);
}

IPackable.cs

interface IPackable
{
    void PackIntoNetMessage(NetOutgoingMessage msg);
    void PopulateFromNetMessage(NetIncomingMessage msg);
}

然后我有特定于应用程序的数据包类,像这样

public class PositionPacket : Packet
{
    public int PosX { get; set; }
    public int PosY { get; set; }
    public override void PackIntoNetMessage(NetOutgoingMessage m)
    {
        m.Write((byte)Networking.PacketTypes.PositionPacket);
        m.Write(PosX);
        m.Write(PosY);
    }
    public override void PopulateFromNetMessage(NetIncomingMessage m)
    {
        PosX = m.ReadInt32();
        PosY = m.ReadInt32();
    }
}

发送数据包很容易,我只是创建一个数据包和PackIntoNetMessage(msg),然后发送它。但是当我尝试接收数据包时,我遇到了一些恼人的结构问题。

我从读取第一个字节

开始
var packetType = (Networking.PacketTypes)incomingMsg.ReadByte();

但是为了得到正确的构造函数,我必须为每个包类型做一个case的切换。

switch (packetType)
{
    case Networking.PacketTypes.PositionPacket:
        incPacket = new Packets.PositionPacket();
        break;
    default:
        incPacket = null;
        break;
}
//Populate packet from net message
incPacket.PopulateFromNetMessage(incomingMsg);

这是我不喜欢的部分。我希望能够使一个通用的包处理系统,处理任何类派生自包。我想反射不是一个好主意,因为它会破坏性能。我该如何构建它来使它更通用?

通用包系统的Lidgren

需要以某种方式创建特定类的实例,以便您可以在启动时使用反射来填充字典,其中包含根据其id存储的来自数据包的所有可用类。

创建实例可以归结为:

var packetTypeId = (Networking.PacketTypes)incomingMsg.ReadByte();
var incPackage = (Package)Activator.CreateInstance(packetTypes[packetTypeId]);

如果你担心创建很多很多的实例,并且期望垃圾收集周期对应用程序的速度有很大的影响,你可以创建一个对象池来回收实例。只要把不再使用的对象放回池中,就可以防止GC循环。

var packetTypeId = (Networking.PacketTypes)incomingMsg.ReadByte();
Type packetType = packetTypes[packetTypeId];
Package incPackage;
if(!pool.TryGetRecycledInstance(packetType, out incPackage))
{
    incPackage = (Package)Activator.CreateInstance(packetType);
}