Simple library for client-server network communication with as less dependencies as possible. Use packets to encapsulate your data which can be encrypted using either RSA or AES. For RSA you can choose to use padding scheme OAEP or not. For AES you can choose to generate a key of length 16, 24 or 32 bytes and use several padding modes like for example PKCS7. Samples included within solution.
PM> Install-Package Arci.Networking
Basic usage of the library. You can find some basic example of a client and a server in the solution. For more advanced example you can check my other project.
Serializer allows to directly serialize/deserialize object into/from Packet object.
// Marks class as serializable to packet with 1 as packet identifier
[PacketClass(1)]
public class MyObject
{
// Marks property to be serialized in specified order
[PacketProperty(1)]
public SByte SByte { get; set; }
[PacketProperty(2)]
public UInt16 UInt16 { get; set; }
[PacketProperty(3)]
public DateTime DateTime { get; set; }
}
var obj = new MyObject();
// Object will be serialized into packet
var packet = obj.ToPacket();
// Deserializes object back to object of type MyObject
obj = packet.FromPacket<MyObject>();
You can choose not to use serializer and serialize/deserialize your objects manualy. Manual serialization is slightly faster (no requirements for reflection) and more flexible as the serializer does not support dynamic objects nor single types.
var buffer = new ByteBuffer()
buffer.Write(uint32Value);
buffer.Write(int16Value);
buffer.Write(byteValue);
buffer.Write(stringValue);
buffer.Write(byteArrayValue);
buffer.Write(dateTimeValue);
Network stream can only work with byte values therefore we need to inform buffer that he needs to write values into stream as a whole byte when we're finished with bit writes (this is only necessary when bits does not form byte already e.g. number_of_bits_written % 8 != 0)
var buffer = new ByteBuffer()
buffer.WriteBit(byteValue & 0x1);
buffer.WriteBit(byteValue & 0x10);
buffer.WriteBit(byteValue & 0x80);
buffer.WriteBit(true);
// Write bits into stream if they do not already form byte
buffer.FlushBits();
var buffer = new ByteBuffer();
// Same as buffer.Write((UInt16)value)
// Flush not required because 16 % 8 == 0
buffer.WriteBits(uint32value, 16);
buffer.WriteBits(uint32Value, 2);
buffer.WriteBits(uint32Value, 4);
// Flush required because we did 2 + 4 bit writes and 6 % 8 != 0
buffer.FlushBits();
UInt64 value represented as 8 byte values. Only bytes that are not 0 will be written to stream. In byte stream before writing guid first you should write bit values to be able to determine which bytes are not 0.
var guid = new PacketGuid(uint64value);
// Order is up to you
buffer.WriteGuidBitStreamInOrder(guid, 0, 1, 2, 3, 4);
// Value can be added in between
buffer.WriteBit(false);
buffer.WriteGuidBitStreamInOrder(guid, 7, 6, 5);
// Flush required because we wrote 9 bits instead of 8
buffer.FlushBits();
buffer.WriteGuidByteStreamInOrder(guid, 0, 1, 2, 3, 4, 5, 6, 7);
// If you just want to save some space and do not care about the order
buffer.Write(guid);
Extends ByteBuffer by adding an identifier to a stream
var packet = new Packet(identifier);
packet.Write(uint32Value);
packet.WriteBit(byteValue & 0x10);
packet.WriteBit(true);
packet.FlushBits();
packet.Write(byteBuffer);
packet.Write(stringValue);
Only usable for Packet class
var packet = new Packet(identifier).Builder()
.Write(uint32Value)
.WriteBit(byteValue & 0x10)
.WriteBit(true)
.FlushBits()
.Write(byteBuffer)
.Write(stringValue).Build();
var packet = new Packet(byteStream);
var uint32value = packet.ReadUInt32();
var guid = new PacketGuid();
packet.ReadGuidBitStreamInOrder(guid, 0, 1, 2, 3, 4, 7, 6, 5);
packet.ReadGuidByteStreamInOrder(guid, 0, 1, 2, 3, 4, 5, 6, 7);
guid = packet.ReadGuid();
var uint64value = (UInt64)guid;
var boolean = packet.ReadBit();
// Reading bit values reads the whole byte into memory and bits are being read from there.
// Necessary if you wish to start bit reading from a new byte.
packet.ClearUnflushedBits();
var client = await Client.CreateAsync("localhost", 10751);
// Send data to server
client.SendPacket(packet);
// Await collection of packets from server
var packets = await tcpClient.ReceiveDataAsync(false);
var server = new Server(IPAddress.Parse("127.0.0.1"), 10751);
// Await new connection
var tcpClient = await server.AcceptClientAsync();
// Await collection of packets from this client
var packets = tcpClient.ReceiveData(false);
// Send data back to client
tcpClient.SendPacket(packet);
var aes = new AesEncryptor() { PaddingMode = PaddingMode.PKCS7 };
var encryptedData = aes.Encrypt(packet.Data);
var decryptedData = aes.Decrypt(encryptedData);
// client can handle encryption if you set an encryptor
client.Encryptor = aes;
var rsa = new RsaEncryptor(RSAKey.RsaParams);
var rsaEncryptedValue = rsa.Encrypt(packet.Data);
var rsaDecryptedValue = rsa.Decrypt(rsaEncryptedValue);
See Wiki for a list of changes between versions
- .NET Standard 2.0