A large number of methods, such as Connection.SendObject and NetworkComms.AppendGlobalIncomingPacketHandler, take an optional SendReceiveOptions object parameter. SendReceiveOptions objects contain all of the options required to modify the sending and receiving of data. Among other features, which we introduce below, it primarily allows you to customise the serialisation, and using the nomenclature of data processing, steps such as compression, encryption, etc.
NetworkComms.Net contains a default SendReceiveOptions, NetworkComms.DefaultSendReceiveOptions, which is used in the absence of any higher priority value. Connection specific SendReceiveOptions can be specified using:
Connection newConn = TCPConnection.GetConnection(connInfo, customSendReceiveOptions);
and also for an isolated sends:
newConn.SendObject("testMessage", objectToSend, customSendReceiveOptions);
For sending, the highest priority SendReceiveOptions is always used, where the order, in decreasing priority is:
- Send Specific Value
- Connection Specific Value – Connection.ConnectionDefaultSendReceiveOptions
- Global Default – NetworkComms.DefaultSendReceiveOptions
Serialisers and Data Processors
Serialisers are used to convert objects into byte arrays and vice versa. You could create your own serialiser by inheriting from DPSBase.DataSerializer, but the following are made available by default:
- ProtobufSerializer – Implements the high performance, open-source, serialiser protobuf-net.
- BinaryFormaterSerializer – Implements the .net BinaryFormatter.
- ExplicitSerializer – Expects any serializable objects to inherit from IExplicitlySerialize, which requires you to implement your own Serialize and Deserialize implementation.
- NullSerializer – Useful for when you send and receive in raw bytes, it acts as a high performance pass-through serializer.
Data processors are used to perform any desired modification of the serialised byte array. You could create your own data processor by inheriting from DPSBase.DataProcessor, but the following are made available by default:
- LZMACompressor – Compression using the LZMA algorithm (Slow Speed, Best Compression).
- SharpZipLibGzipCompressor – Compression using the GZip algorthim (Good Speed, Good Compression).
- RijndaelPSKEncrypter – Symmetrical key encryption, see our specific encryption tutorial here.
Instances of data serialisers or data processors can be accessed via the DPSManager:
//Get an instance of the ProtobufSerializer DataSerializer serializer = DPSManager.GetDataSerializer<ProtobufSerializer>(); //Get an instance of the LZMACompressor DataProcessor processor = DPSManager.GetDataProcessor<SevenZipLZMACompressor.LZMACompressor>();
To create your own custom SendReceiveOptions objects please see the convenient type constructors here, a quick example:
//Create a custom SendReceiveOptions object which uses the // ProtobufSerializer serialiser and QuickLZ compression data processor SendReceiveOptions customSendReceiveOptions = new SendReceiveOptions<ProtobufSerializer, QuickLZCompressor.QuickLZ>();
SendReceiveOptions objects contain an internal Dictionary<string,string>, SendReceiveOptions.Options,which is used to flexibly store further options which may be required by data serialisers or data processors. You are free to add your own options, but the following dictionary keys are used internally by NetworkComms.Net:
- IncludePacketConstructionTime – If key present the sending client will include the packet creation time in the packet header. This can be examined by the receiving end using PacketHeader.GetOption.
- ReceiveConfirmationRequired – If key present the sending method will only return successfully if the send was successfully received by the remote end. This is all handled internally by NetworkComms.Net. If the send is not successfully received after NetworkComms.PacketConfirmationTimeoutMS the send method will throw an ConfirmationTimeoutException.
- ReceiveHandlePriority – Please see the below section on Incoming Data Handlers for more information.
Data Prioritisation – Packet Handlers
When an incoming packet is received it is typically enqueued in NetworkComms.CommsThreadPool for later execution. Incoming packets are handled using a flexible QueueItemPriority. Reserved internal packet types and packets marked with QueueItemPriority.Highest are not enqueued but handled in real time by the thread handling the incoming data. You are free to specify the queue item priority used by packet handlers by setting the ReceiveHandlePriority property of a suitable SendReceiveOptions, to the desired priority, e.g.:
//Clone the existing default SendReceiveOptions SendReceiveOptions highPrioReceiveSRO = (SendReceiveOptions)NetworkComms.DefaultSendReceiveOptions.Clone(); //Set the ReceiveHandlePriority property highPrioReceiveSRO.ReceiveHandlePriority = QueueItemPriority.AboveNormal; //Append a global incoming packet handler for the "ImportantPacket" type using the high priority SendReceiveOptions NetworkComms.AppendGlobalIncomingPacketHandler<string>("ImportantPacket", MethodToRun, highPrioReceiveSRO);
Caution: Worker threads within NetworkComms.CommsThreadPool will execute all queued packets with higher priorities first. e.g. if a large proportion of high priority packets are received in a high bandwidth application, lower priority packets may never be handled.