Show / Hide Table of Contents

NetPacketProcessor

Fast specialized for network purposes serializer.
It supports classes with public properties with "get" and "set" methods or classes/structs which implements INetSerializable.
Serializer adds some overhead to packet size: 64 bit hash of class name and namespace (8 bytes). All other class fields will be as is in resulting packet.

Serialization speed comparsion

Serialization 100000 times of simple structure from example (NET 4.5): Serializer|Time|Size ---|---|---| BinaryFormatter|3334 ms|1096 bytes NetSerializer (first run)|45 ms|204 bytes NetSerializer (second run)|37 ms|204 bytes Raw|24 ms|204 bytes

Supported property types

byte sbyte short ushort int uint long ulong float double bool string char IPEndPoint

Arrays of all these types (and custom types) are also supported.
Enums are supported but work a bit slower than other types.

Custom types

NetPacketProcessor doesn't support nested structs or classes, but you can register your own custom type processors.
That useful for game engine types such as Vector3 and Quaternion (in Unity3d).

// Your packet that will be sent over network
class SamplePacket
{
	// Both property and array are supported
    public MyType SomeMyType { get; set; }
    public MyType[] SomeMyTypes { get; set; } 
}

// Some custom type variant 1: Basic struct
struct MyType
{
    public int Value1;
    public string Value2;

    public static void Serialize(NetDataWriter writer, SomeMyType mytype)
    {
        writer.Put(mytype.Value1);
        writer.Put(mytype.Value2);
    }

    public static MyType Deserialize(NetDataReader reader)
    {
        MyType res = new MyType();
        res.Value1 = reader.GetInt();
        res.Value2 = reader.GetString();
        return res;
    }
}
...
netPacketProcessor = new NetPacketProcessor();
netPacketProcessor.RegisterNestedType( MyType.Serialize, MyType.Deserialize ); // Supply Serialization methods

You can also implement INetSerializable interface:

// Some custom type variant 2: INetSerializable struct
struct MyType : INetSerializable
{
    public int Value1;
    public string Value2;

    public void Serialize(NetDataWriter writer)
    {
        writer.Put(Value1);
        writer.Put(Value2);
    }

    public void Deserialize(NetDataReader reader)
    {
        Value1 = reader.GetInt();
        Value2 = reader.GetString();
    }
}
...
netPacketProcessor = new NetPacketProcessor();
netPacketProcessor.RegisterNestedType<MyType>(); // Serialization handled automatically thanks to INetSerializable

If you want to use a class instead of a struct you must implement the INetSerializable interface and provide a constructor:

// Some custom type variant 3: Class, must implement INetSerializable
class MyType : INetSerializable
{
    public int Value1;
    public string Value2;

    public void Serialize(NetDataWriter writer)
    {
        writer.Put(Value1);
        writer.Put(Value2);
    }

    public void Deserialize(NetDataReader reader)
    {
        Value1 = reader.GetInt();
        Value2 = reader.GetString();
    }
}
...
netPacketProcessor = new NetPacketProcessor();
netPacketProcessor.RegisterNestedType<MyType>(() => { return new SomeMyType(); }); // Must provide constructor

Usage example

For full example look at source SerializerBenchmark

Packet

class SamplePacket
{
	// All of these will be automatically serialized and deserialized
    public string SomeString { get; set; }
    public float SomeFloat { get; set; }
    public int[] SomeIntArray { get; set; }
}

Sending / recieving

// Client
class SomeClientListener : INetEventListener
{
   private readonly NetPacketProcessor _netPacketProcessor = new NetPacketProcessor();
...
   public void OnPeerConnected(NetPeer peer)
   {
		// After connection is established you will have the server as a NetPeer
       SamplePacket packet = new SamplePacket
       {
           SomeFloat = 3.42f,
           SomeIntArray = new[] {6, 5, 4},
           SomeString = "Test String",
       }
       // Serialize the packet with NetSerializer and send it to the peer (server)
       peer.Send(_netPacketProcessor.Write(packet), DeliveryMethod.ReliableOrdered);
       //You can also use _netPacketProcessor.Send(peer, packet, DeliveryMethod.ReliableOrdered);
   }
}

// Server 
class SomeServerListener : INetEventListener
{
    private readonly NetPacketProcessor _netPacketProcessor = new NetPacketProcessor();

    public SomeServerListener()
    {
        // Subscribe to recieving packets.        
        _netPacketProcessor.SubscribeReusable<SamplePacket, NetPeer>(OnSamplePacketReceived);
    }

	// Handler for SamplePacket, registered in constructor above
    private void OnSamplePacketReceived(SamplePacket samplePacket, NetPeer peer)
    {
        Console.WriteLine("[Server] ReceivedPacket:\n" + samplePacket.SomeString);
    }

	// INetEventListener function.
    public void OnNetworkReceive(NetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod)
    {
        Console.WriteLine("[Server] received data. Processing...");
        // Deserializes packet and calls the handler registered in constructor
        _netPacketProcessor.ReadAllPackets(reader, peer);
    }
}

Mini FAQ

Q: NetPacketProcessor throws "Undefined packet in NetDataReader" but all packets are registered.
A: This can happen when packet definitions resides in different namespaces. Check that registered packet classes/structs are in the same namespace on both ends. To avoid this error altogether, use shared code/-assembly for packets.

In this article
Back to top Generated by DocFX