-
Notifications
You must be signed in to change notification settings - Fork 5
3.SSLClient ‐ Server
- Uses standard TLS authentication.
- It is core SSL model where byte data is send very efficiently.
- It is optimised for high traffic small messages where under load messages are concataned and sent as batch.
- It is capable of large transfers like file. But it is reccomended to chink the file instead of sending it as singleton.
- It is using memory pooling, which reduces GC pressure significantly.
- It is also optimised for high amount of connect disconnect scenarios.
Ssl requires certificates to work with. In this case you can either load an existing certificate or generate self signed certificate.
Note that certificate generation is not supported on Unity
var scert = new X509Certificate2("server.pfx", "greenpass");
var cert = new X509Certificate2("client.pfx", "greenpass");
//using NetworkLibrary.Components.Crypto.Certificate;
var scert = CertificateGenerator.GenerateSelfSignedCertificate();
var cert = CertificateGenerator.GenerateSelfSignedCertificate();
To initialise server and you can simply:
SslServer server = new SslServer(20008,scert);
server.OnClientAccepted += HandleAccept;
server.OnClientDisconnected += HandleDisconnect;
server.OnBytesReceived += ServerBytesReceived;
server.StartServer();
SslClient client = new SslClient(cert);
client.OnDisconnected += HandleDC;
client.OnBytesReceived += ClientBytesReceived;
client.Connect("127.0.0.1", 20008);
You can also use empty constructor or pass a null certificate. System will generate self signed certificate.
SslServer server = new SslServer(20008);
SslClient client = new SslClient();
Certificate validation is handled with a validation callback which slall return true if the validation is succesfull. Note that, self signed ceritifactes will generate ssl policy errors.
server.RemoteCertificateValidationCallback;
server.RemoteCertificateValidationCallback += (_, _, _, _) => { return true; };
If you dont assign a callback default looks as this:
private bool DefaultValidationCallback(object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.None)
return true;
return false;
}
To send data with client:
byte[] data = new byte[10000];
client.SendAsync(data);
client.SendAsync(data, offset:200, count:50);
To send data with server:
Guid ClientId;
server.SendAsync(ClientId, data);
server.SendAsync(ClientId, data, offset:200, count:50);
Where client id comes from on accepted callback.
Sends never block the caller(until you reached max buffered memory limit). If send operation detects the underlying socket is busy with previous send, it will queue/buffer the messages. Once the send operation is complete socket will check the state of message buffer. if buffer is not empty it will loop another send. Note that this operation sends entire buffer in bulk, not a single message. This provides great efficiency on small high traffic messages.
Receive is an async callback from socket. To keep message consistency Receive wont be looped until your OnBytesReceived callback returns.
Remember that the buffer you receive on your callback is sockets buffer region.
If you want to store this bytes, you must do a copy or it will be overwritten on next receive.
I reccommend not changing the default configuration in terms of socket and send receive buffer sizes, unless you have a spesific reason.
if you want to limit your max memory you can change:
server.MaxIndexedMemoryPerClient;
client.MaxIndexedMemory;
which will block the traffic once the threashold is reached, until bufferred bytes are cleared.
There is an important configuration you should take into account Which you must set before starting the server:
client.GatherConfig = ScatterGatherConfig.UseQueue;
server.GatherConfig = ScatterGatherConfig.UseBuffer;
Determines whether to use queue or buffer for message gathering mechanism.
UseQueue requires your byte[] sources to be not modified after send.
Queue copies the data during the send operation from the array reference.
Hence, your data may be copied asyncronusly.
UseBuffer will copy your data into a buffer on caller thread immediately. During socket send, a buffer swap will be performed(WriteBuffer and SenbdBuffer).
This means you can modify or reuse your data safely.
Queue implementation is more efficient and maybe suitable static resources or for short lived disposable data i.e.(Encoding.UTF8.GetBytes(string)).
Buffer provides data safety where your send byte[] or segment can be reused for manupulation, i.e. Streams.
All examples cam be found on Examples.
//var scert = new X509Certificate2("server.pfx", "greenpass");
//var cert = new X509Certificate2("client.pfx", "greenpass");
var scert = CertificateGenerator.GenerateSelfSignedCertificate();
var cert = CertificateGenerator.GenerateSelfSignedCertificate();
SslServer server = new SslServer(20008,scert);
server.OnBytesReceived += ServerBytesReceived;
server.RemoteCertificateValidationCallback += (_, _, _, _) => { return true; };
server.StartServer();
SslClient client = new SslClient(cert);
client.OnBytesReceived += ClientBytesReceived;
client.RemoteCertificateValidationCallback += (_, _, _, _) => { return true; };
client.Connect("127.0.0.1", 20008);
client.SendAsync(Encoding.UTF8.GetBytes("Hello I'm a client!"));
void ServerBytesReceived(Guid clientId, byte[] bytes, int offset, int count)
{
Console.WriteLine(Encoding.UTF8.GetString(bytes, offset, count));
server.SendBytesToClient(clientId, Encoding.UTF8.GetBytes("Hello I'm the server"));
}
void ClientBytesReceived(byte[] bytes, int offset, int count)
{
Console.WriteLine(Encoding.UTF8.GetString(bytes, offset, count));
}