简体   繁体   English

Lidgren的通用数据包系统

[英]Generic packet system for Lidgren

I'm using Lidgren.Networking to send data between server and clients in a client/server architecture. 我正在使用Lidgren.Networking在客户端/服务器体系结构中的服务器和客户端之间发送数据。 I have created a Packet class to use when sending packets over the network. 我创建了一个Packet类,用于在网络上发送数据包时使用。

Packet.cs Packet.cs

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

IPackable.cs IPackable.cs

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

Then I have application specific packet classes like this 然后我有像这样的应用程序特定的数据包类

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();
    }
}

Sending the packets is easy, I just create a packet and PackIntoNetMessage(msg) and then send it. 发送数据包很容易,我只需创建一个数据包和PackIntoNetMessage(msg),然后发送它即可。 But it's when I try to recieve packets I get some annoying structural problems. 但是,当我尝试接收数据包时,我遇到了一些令人讨厌的结构性问题。

I start by reading the first byte 我从读取第一个字节开始

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

but then I have to make a switch with a case for each packet type in order the get the correct constructor. 但是然后我必须对每种数据包类型的大小写进行切换,以获取正确的构造函数。

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

This is the part that I don't like. 这是我不喜欢的部分。 I want to be able to make a generic packet handling system that handles any class deriving from Packet. 我希望能够制作一个通用的数据包处理系统,以处理任何从Packet派生的类。 I guess reflection wont be a good idea since it will kill the performance. 我想反射将不是一个好主意,因为它将破坏性能。 How shall I structure this to make it more generic? 我应该如何构造它使其更通用?

The instance of the specific class needs to be created somehow so you could use reflection on start-up to fill a dictionary with all available classes that derive from Packet stored by their ids. 需要以某种方式创建特定类的实例,因此您可以在启动时使用反射功能,以字典的形式填充所有派生自ID的Packet派生的可用类。

Creating an instance would then boil down to: 然后创建一个实例可以归结为:

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

If you are worried about creating many, many instances and expect garbage collection cycles with big impact on your application's speed you could create a pool of objects that recycles instances. 如果您担心创建许多实例,并希望垃圾回收周期对应用程序的速度产生重大影响,则可以创建一个回收实例的对象池。 As long as you drop objects, that are no longer used, back into the pool you could prevent GC cycles. 只要将不再使用的对象放回池中,就可以防止GC循环。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM