通用包系统的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);
这是我不喜欢的部分。我希望能够使一个通用的包处理系统,处理任何类派生自包。我想反射不是一个好主意,因为它会破坏性能。我该如何构建它来使它更通用?
需要以某种方式创建特定类的实例,以便您可以在启动时使用反射来填充字典,其中包含根据其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);
}