- Notifications
You must be signed in to change notification settings - Fork592
Ultra fast and low latency asynchronous socket server & client C# .NET Core library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and 10K connections problem solution
License
chronoxor/NetCoreServer
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Ultra fast and low latency asynchronous socket server & client C# .NET Corelibrary with support TCP, SSL, UDP, Unix Domain Socket, HTTP, HTTPS, WebSocket protocols and10K connections problemsolution.
Has integration with high-level message protocol based onFast Binary Encoding
NetCoreServer documentation
NetCoreServer downloads
- Features
- Requirements
- How to build?
- Examples
- Example: TCP chat server
- Example: TCP chat client
- Example: SSL chat server
- Example: SSL chat client
- Example: UDP echo server
- Example: UDP echo client
- Example: UDP multicast server
- Example: UDP multicast client
- Example: Unix Domain Socket chat server
- Example: Unix Domain Socket chat client
- Example: Simple protocol
- Example: Simple protocol server
- Example: Simple protocol client
- Example: HTTP server
- Example: HTTP client
- Example: HTTPS server
- Example: HTTPS client
- Example: WebSocket chat server
- Example: WebSocket chat client
- Example: WebSocket secure chat server
- Example: WebSocket secure chat client
- Performance
- OpenSSL certificates
- Cross platform (Linux, MacOS, Windows)
- Asynchronous communication
- Supported transport protocols:TCP,SSL,UDP,UDP multicast,Unix Domain Socket
- Supported Web protocols:HTTP,HTTPS,WebSocket,WebSocket secure
- SupportedSwagger OpenAPI iterative documentation
- Supported message protocol based onFast Binary Encoding
- Linux
- MacOS
- Windows
- .NET 6.0
- 7-Zip
- cmake
- git
- Visual Studio
Optional:
git clone https://github.com/chronoxor/NetCoreServer.gitcd NetCoreServer
cd build./unix.sh
cd build./unix.sh
Open and buildNetCoreServer.sln or run the build script:
cd buildvs.bat
The build script will create "release" directory with zip files:
- NetCoreServer.zip - C# Server assembly
- Benchmarks.zip - C# Server benchmarks
- Examples.zip - C# Server examples
Here comes the example of the TCP chat server. It handles multiple TCP clientsessions and multicast received message from any session to all ones. Also itis possible to send admin message directly from the server.
usingSystem;usingSystem.Net;usingSystem.Net.Sockets;usingSystem.Text;usingNetCoreServer;namespaceTcpChatServer{classChatSession:TcpSession{publicChatSession(TcpServerserver):base(server){}protectedoverridevoidOnConnected(){Console.WriteLine($"Chat TCP session with Id{Id} connected!");// Send invite messagestringmessage="Hello from TCP chat! Please send a message or '!' to disconnect the client!";SendAsync(message);}protectedoverridevoidOnDisconnected(){Console.WriteLine($"Chat TCP session with Id{Id} disconnected!");}protectedoverridevoidOnReceived(byte[]buffer,longoffset,longsize){stringmessage=Encoding.UTF8.GetString(buffer,(int)offset,(int)size);Console.WriteLine("Incoming: "+message);// Multicast message to all connected sessionsServer.Multicast(message);// If the buffer starts with '!' the disconnect the current sessionif(message=="!")Disconnect();}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Chat TCP session caught an error with code{error}");}}classChatServer:TcpServer{publicChatServer(IPAddressaddress,intport):base(address,port){}protectedoverrideTcpSessionCreateSession(){returnnewChatSession(this);}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Chat TCP server caught an error with code{error}");}}classProgram{staticvoidMain(string[]args){// TCP server portintport=1111;if(args.Length>0)port=int.Parse(args[0]);Console.WriteLine($"TCP server port:{port}");Console.WriteLine();// Create a new TCP chat servervarserver=newChatServer(IPAddress.Any,port);// Start the serverConsole.Write("Server starting...");server.Start();Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Restart the serverif(line=="!"){Console.Write("Server restarting...");server.Restart();Console.WriteLine("Done!");continue;}// Multicast admin message to all sessionsline="(admin) "+line;server.Multicast(line);}// Stop the serverConsole.Write("Server stopping...");server.Stop();Console.WriteLine("Done!");}}}
Here comes the example of the TCP chat client. It connects to the TCP chatserver and allows to send message to it and receive new messages.
usingSystem;usingSystem.Net.Sockets;usingSystem.Text;usingSystem.Threading;usingTcpClient=NetCoreServer.TcpClient;namespaceTcpChatClient{classChatClient:TcpClient{publicChatClient(stringaddress,intport):base(address,port){}publicvoidDisconnectAndStop(){_stop=true;DisconnectAsync();while(IsConnected)Thread.Yield();}protectedoverridevoidOnConnected(){Console.WriteLine($"Chat TCP client connected a new session with Id{Id}");}protectedoverridevoidOnDisconnected(){Console.WriteLine($"Chat TCP client disconnected a session with Id{Id}");// Wait for a while...Thread.Sleep(1000);// Try to connect againif(!_stop)ConnectAsync();}protectedoverridevoidOnReceived(byte[]buffer,longoffset,longsize){Console.WriteLine(Encoding.UTF8.GetString(buffer,(int)offset,(int)size));}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Chat TCP client caught an error with code{error}");}privatebool_stop;}classProgram{staticvoidMain(string[]args){// TCP server addressstringaddress="127.0.0.1";if(args.Length>0)address=args[0];// TCP server portintport=1111;if(args.Length>1)port=int.Parse(args[1]);Console.WriteLine($"TCP server address:{address}");Console.WriteLine($"TCP server port:{port}");Console.WriteLine();// Create a new TCP chat clientvarclient=newChatClient(address,port);// Connect the clientConsole.Write("Client connecting...");client.ConnectAsync();Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Disconnect the clientif(line=="!"){Console.Write("Client disconnecting...");client.DisconnectAsync();Console.WriteLine("Done!");continue;}// Send the entered text to the chat serverclient.SendAsync(line);}// Disconnect the clientConsole.Write("Client disconnecting...");client.DisconnectAndStop();Console.WriteLine("Done!");}}}
Here comes the example of the SSL chat server. It handles multiple SSL clientsessions and multicast received message from any session to all ones. Also itis possible to send admin message directly from the server.
This example is very similar to the TCP one except the code that prepares SSLcontext and handshake handler.
usingSystem;usingSystem.Net;usingSystem.Net.Sockets;usingSystem.Security.Authentication;usingSystem.Security.Cryptography.X509Certificates;usingSystem.Text;usingNetCoreServer;namespaceSslChatServer{classChatSession:SslSession{publicChatSession(SslServerserver):base(server){}protectedoverridevoidOnConnected(){Console.WriteLine($"Chat SSL session with Id{Id} connected!");}protectedoverridevoidOnHandshaked(){Console.WriteLine($"Chat SSL session with Id{Id} handshaked!");// Send invite messagestringmessage="Hello from SSL chat! Please send a message or '!' to disconnect the client!";Send(message);}protectedoverridevoidOnDisconnected(){Console.WriteLine($"Chat SSL session with Id{Id} disconnected!");}protectedoverridevoidOnReceived(byte[]buffer,longoffset,longsize){stringmessage=Encoding.UTF8.GetString(buffer,(int)offset,(int)size);Console.WriteLine("Incoming: "+message);// Multicast message to all connected sessionsServer.Multicast(message);// If the buffer starts with '!' the disconnect the current sessionif(message=="!")Disconnect();}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Chat SSL session caught an error with code{error}");}}classChatServer:SslServer{publicChatServer(SslContextcontext,IPAddressaddress,intport):base(context,address,port){}protectedoverrideSslSessionCreateSession(){returnnewChatSession(this);}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Chat SSL server caught an error with code{error}");}}classProgram{staticvoidMain(string[]args){// SSL server portintport=2222;if(args.Length>0)port=int.Parse(args[0]);Console.WriteLine($"SSL server port:{port}");Console.WriteLine();// Create and prepare a new SSL server contextvarcontext=newSslContext(SslProtocols.Tls12,newX509Certificate2("server.pfx","qwerty"));// Create a new SSL chat servervarserver=newChatServer(context,IPAddress.Any,port);// Start the serverConsole.Write("Server starting...");server.Start();Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Restart the serverif(line=="!"){Console.Write("Server restarting...");server.Restart();Console.WriteLine("Done!");continue;}// Multicast admin message to all sessionsline="(admin) "+line;server.Multicast(line);}// Stop the serverConsole.Write("Server stopping...");server.Stop();Console.WriteLine("Done!");}}}
Here comes the example of the SSL chat client. It connects to the SSL chatserver and allows to send message to it and receive new messages.
This example is very similar to the TCP one except the code that prepares SSLcontext and handshake handler.
usingSystem;usingSystem.Net.Sockets;usingSystem.Security.Authentication;usingSystem.Security.Cryptography.X509Certificates;usingSystem.Text;usingSystem.Threading;usingNetCoreServer;namespaceSslChatClient{classChatClient:SslClient{publicChatClient(SslContextcontext,stringaddress,intport):base(context,address,port){}publicvoidDisconnectAndStop(){_stop=true;DisconnectAsync();while(IsConnected)Thread.Yield();}protectedoverridevoidOnConnected(){Console.WriteLine($"Chat SSL client connected a new session with Id{Id}");}protectedoverridevoidOnHandshaked(){Console.WriteLine($"Chat SSL client handshaked a new session with Id{Id}");}protectedoverridevoidOnDisconnected(){Console.WriteLine($"Chat SSL client disconnected a session with Id{Id}");// Wait for a while...Thread.Sleep(1000);// Try to connect againif(!_stop)ConnectAsync();}protectedoverridevoidOnReceived(byte[]buffer,longoffset,longsize){Console.WriteLine(Encoding.UTF8.GetString(buffer,(int)offset,(int)size));}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Chat SSL client caught an error with code{error}");}privatebool_stop;}classProgram{staticvoidMain(string[]args){// SSL server addressstringaddress="127.0.0.1";if(args.Length>0)address=args[0];// SSL server portintport=2222;if(args.Length>1)port=int.Parse(args[1]);Console.WriteLine($"SSL server address:{address}");Console.WriteLine($"SSL server port:{port}");Console.WriteLine();// Create and prepare a new SSL client contextvarcontext=newSslContext(SslProtocols.Tls12,newX509Certificate2("client.pfx","qwerty"),(sender,certificate,chain,sslPolicyErrors)=>true);// Create a new SSL chat clientvarclient=newChatClient(context,address,port);// Connect the clientConsole.Write("Client connecting...");client.ConnectAsync();Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Disconnect the clientif(line=="!"){Console.Write("Client disconnecting...");client.DisconnectAsync();Console.WriteLine("Done!");continue;}// Send the entered text to the chat serverclient.SendAsync(line);}// Disconnect the clientConsole.Write("Client disconnecting...");client.DisconnectAndStop();Console.WriteLine("Done!");}}}
Here comes the example of the UDP echo server. It receives a datagram mesagefrom any UDP client and resend it back without any changes.
usingSystem;usingSystem.Net;usingSystem.Net.Sockets;usingSystem.Text;usingNetCoreServer;namespaceUdpEchoServer{classEchoServer:UdpServer{publicEchoServer(IPAddressaddress,intport):base(address,port){}protectedoverridevoidOnStarted(){// Start receive datagramsReceiveAsync();}protectedoverridevoidOnReceived(EndPointendpoint,byte[]buffer,longoffset,longsize){Console.WriteLine("Incoming: "+Encoding.UTF8.GetString(buffer,(int)offset,(int)size));// Echo the message back to the senderSendAsync(endpoint,buffer,0,size);}protectedoverridevoidOnSent(EndPointendpoint,longsent){// Continue receive datagramsReceiveAsync();}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Echo UDP server caught an error with code{error}");}}classProgram{staticvoidMain(string[]args){// UDP server portintport=3333;if(args.Length>0)port=int.Parse(args[0]);Console.WriteLine($"UDP server port:{port}");Console.WriteLine();// Create a new UDP echo servervarserver=newEchoServer(IPAddress.Any,port);// Start the serverConsole.Write("Server starting...");server.Start();Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Restart the serverif(line=="!"){Console.Write("Server restarting...");server.Restart();Console.WriteLine("Done!");}}// Stop the serverConsole.Write("Server stopping...");server.Stop();Console.WriteLine("Done!");}}}
Here comes the example of the UDP echo client. It sends user datagram messageto UDP server and listen for response.
usingSystem;usingSystem.Net;usingSystem.Net.Sockets;usingSystem.Text;usingSystem.Threading;usingUdpClient=NetCoreServer.UdpClient;namespaceUdpEchoClient{classEchoClient:UdpClient{publicEchoClient(stringaddress,intport):base(address,port){}publicvoidDisconnectAndStop(){_stop=true;Disconnect();while(IsConnected)Thread.Yield();}protectedoverridevoidOnConnected(){Console.WriteLine($"Echo UDP client connected a new session with Id{Id}");// Start receive datagramsReceiveAsync();}protectedoverridevoidOnDisconnected(){Console.WriteLine($"Echo UDP client disconnected a session with Id{Id}");// Wait for a while...Thread.Sleep(1000);// Try to connect againif(!_stop)Connect();}protectedoverridevoidOnReceived(EndPointendpoint,byte[]buffer,longoffset,longsize){Console.WriteLine("Incoming: "+Encoding.UTF8.GetString(buffer,(int)offset,(int)size));// Continue receive datagramsReceiveAsync();}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Echo UDP client caught an error with code{error}");}privatebool_stop;}classProgram{staticvoidMain(string[]args){// UDP server addressstringaddress="127.0.0.1";if(args.Length>0)address=args[0];// UDP server portintport=3333;if(args.Length>1)port=int.Parse(args[1]);Console.WriteLine($"UDP server address:{address}");Console.WriteLine($"UDP server port:{port}");Console.WriteLine();// Create a new TCP chat clientvarclient=newEchoClient(address,port);// Connect the clientConsole.Write("Client connecting...");client.Connect();Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Disconnect the clientif(line=="!"){Console.Write("Client disconnecting...");client.Disconnect();Console.WriteLine("Done!");continue;}// Send the entered text to the chat serverclient.Send(line);}// Disconnect the clientConsole.Write("Client disconnecting...");client.DisconnectAndStop();Console.WriteLine("Done!");}}}
Here comes the example of the UDP multicast server. It use multicast IP addressto multicast datagram messages to all client that joined corresponding UDPmulticast group.
usingSystem;usingSystem.Net;usingSystem.Net.Sockets;usingNetCoreServer;namespaceUdpMulticastServer{classMulticastServer:UdpServer{publicMulticastServer(IPAddressaddress,intport):base(address,port){}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Multicast UDP server caught an error with code{error}");}}classProgram{staticvoidMain(string[]args){// UDP multicast addressstringmulticastAddress="239.255.0.1";if(args.Length>0)multicastAddress=args[0];// UDP multicast portintmulticastPort=3334;if(args.Length>1)multicastPort=int.Parse(args[1]);Console.WriteLine($"UDP multicast address:{multicastAddress}");Console.WriteLine($"UDP multicast port:{multicastPort}");Console.WriteLine();// Create a new UDP multicast servervarserver=newMulticastServer(IPAddress.Any,0);// Start the multicast serverConsole.Write("Server starting...");server.Start(multicastAddress,multicastPort);Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Restart the serverif(line=="!"){Console.Write("Server restarting...");server.Restart();Console.WriteLine("Done!");continue;}// Multicast admin message to all sessionsline="(admin) "+line;server.Multicast(line);}// Stop the serverConsole.Write("Server stopping...");server.Stop();Console.WriteLine("Done!");}}}
Here comes the example of the UDP multicast client. It use multicast IP addressand joins UDP multicast group in order to receive multicasted datagram messagesfrom UDP server.
usingSystem;usingSystem.Net;usingSystem.Net.Sockets;usingSystem.Text;usingSystem.Threading;usingUdpClient=NetCoreServer.UdpClient;namespaceUdpMulticastClient{classMulticastClient:UdpClient{publicstringMulticast;publicMulticastClient(stringaddress,intport):base(address,port){}publicvoidDisconnectAndStop(){_stop=true;Disconnect();while(IsConnected)Thread.Yield();}protectedoverridevoidOnConnected(){Console.WriteLine($"Multicast UDP client connected a new session with Id{Id}");// Join UDP multicast groupJoinMulticastGroup(Multicast);// Start receive datagramsReceiveAsync();}protectedoverridevoidOnDisconnected(){Console.WriteLine($"Multicast UDP client disconnected a session with Id{Id}");// Wait for a while...Thread.Sleep(1000);// Try to connect againif(!_stop)Connect();}protectedoverridevoidOnReceived(EndPointendpoint,byte[]buffer,longoffset,longsize){Console.WriteLine("Incoming: "+Encoding.UTF8.GetString(buffer,(int)offset,(int)size));// Continue receive datagramsReceiveAsync();}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Multicast UDP client caught an error with code{error}");}privatebool_stop;}classProgram{staticvoidMain(string[]args){// UDP listen addressstringlistenAddress="0.0.0.0";if(args.Length>0)listenAddress=args[0];// UDP multicast addressstringmulticastAddress="239.255.0.1";if(args.Length>1)multicastAddress=args[1];// UDP multicast portintmulticastPort=3334;if(args.Length>2)multicastPort=int.Parse(args[2]);Console.WriteLine($"UDP listen address:{listenAddress}");Console.WriteLine($"UDP multicast address:{multicastAddress}");Console.WriteLine($"UDP multicast port:{multicastPort}");Console.WriteLine();// Create a new TCP chat clientvarclient=newMulticastClient(listenAddress,multicastPort);client.SetupMulticast(true);client.Multicast=multicastAddress;// Connect the clientConsole.Write("Client connecting...");client.Connect();Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Disconnect the clientif(line=="!"){Console.Write("Client disconnecting...");client.Disconnect();Console.WriteLine("Done!");continue;}}// Disconnect the clientConsole.Write("Client disconnecting...");client.DisconnectAndStop();Console.WriteLine("Done!");}}}
Here comes the example of the Unix Domain Socket chat server. It handlesmultiple Unix Domain Socket client sessions and multicast received message fromany session to all ones. Also it is possible to send admin message directlyfrom the server.
usingSystem;usingSystem.IO;usingSystem.Net.Sockets;usingSystem.Text;usingNetCoreServer;namespaceUdsChatServer{classChatSession:UdsSession{publicChatSession(UdsServerserver):base(server){}protectedoverridevoidOnConnected(){Console.WriteLine($"Chat Unix Domain Socket session with Id{Id} connected!");// Send invite messagestringmessage="Hello from Unix Domain Socket chat! Please send a message or '!' to disconnect the client!";SendAsync(message);}protectedoverridevoidOnDisconnected(){Console.WriteLine($"Chat Unix Domain Socket session with Id{Id} disconnected!");}protectedoverridevoidOnReceived(byte[]buffer,longoffset,longsize){stringmessage=Encoding.UTF8.GetString(buffer,(int)offset,(int)size);Console.WriteLine("Incoming: "+message);// Multicast message to all connected sessionsServer.Multicast(message);// If the buffer starts with '!' the disconnect the current sessionif(message=="!")Disconnect();}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Chat Unix Domain Socket session caught an error with code{error}");}}classChatServer:UdsServer{publicChatServer(stringpath):base(path){}protectedoverrideUdsSessionCreateSession(){returnnewChatSession(this);}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Chat Unix Domain Socket server caught an error with code{error}");}}classProgram{staticvoidMain(string[]args){// Unix Domain Socket pathstringpath=Path.Combine(Path.GetTempPath(),"chat.sock");if(args.Length>0)path=args[0];Console.WriteLine($"Unix Domain Socket server path:{path}");Console.WriteLine();// Create a new Unix Domain Socket chat servervarserver=newChatServer(path);// Start the serverConsole.Write("Server starting...");server.Start();Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Restart the serverif(line=="!"){Console.Write("Server restarting...");server.Restart();Console.WriteLine("Done!");continue;}// Multicast admin message to all sessionsline="(admin) "+line;server.Multicast(line);}// Stop the serverConsole.Write("Server stopping...");server.Stop();Console.WriteLine("Done!");}}}
Here comes the example of the Unix Domain Socket chat client. It connects tothe Unix Domain Socket chat server and allows to send message to it and receivenew messages.
usingSystem;usingSystem.IO;usingSystem.Net.Sockets;usingSystem.Text;usingSystem.Threading;usingUdsClient=NetCoreServer.UdsClient;namespaceUdsChatClient{classChatClient:UdsClient{publicChatClient(stringpath):base(path){}publicvoidDisconnectAndStop(){_stop=true;DisconnectAsync();while(IsConnected)Thread.Yield();}protectedoverridevoidOnConnected(){Console.WriteLine($"Chat Unix Domain Socket client connected a new session with Id{Id}");}protectedoverridevoidOnDisconnected(){Console.WriteLine($"Chat Unix Domain Socket client disconnected a session with Id{Id}");// Wait for a while...Thread.Sleep(1000);// Try to connect againif(!_stop)ConnectAsync();}protectedoverridevoidOnReceived(byte[]buffer,longoffset,longsize){Console.WriteLine(Encoding.UTF8.GetString(buffer,(int)offset,(int)size));}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Chat Unix Domain Socket client caught an error with code{error}");}privatebool_stop;}classProgram{staticvoidMain(string[]args){// Unix Domain Socket pathstringpath=Path.Combine(Path.GetTempPath(),"chat.sock");if(args.Length>0)path=args[0];Console.WriteLine($"Unix Domain Socket server path:{path}");Console.WriteLine();// Create a new Unix Domain Socket chat clientvarclient=newChatClient(path);// Connect the clientConsole.Write("Client connecting...");client.ConnectAsync();Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Disconnect the clientif(line=="!"){Console.Write("Client disconnecting...");client.DisconnectAsync();Console.WriteLine("Done!");continue;}// Send the entered text to the chat serverclient.SendAsync(line);}// Disconnect the clientConsole.Write("Client disconnecting...");client.DisconnectAndStop();Console.WriteLine("Done!");}}}
Simple protocol is defined insimple.fbe file:
/* Simple Fast Binary Encoding protocol for CppServer https://github.com/chronoxor/FastBinaryEncoding Generate protocol command: fbec --csharp --proto --input=simple.fbe --output=.*/// Domain declarationdomain com.chronoxor// Package declarationpackage simple// Protocol versionversion 1.0// Simple request message[request][response(SimpleResponse)][reject(SimpleReject)]messageSimpleRequest{// Request Id uuid [id] = uuid1;// Request message string Message;}// Simple responsemessageSimpleResponse{// Response Id uuid [id] = uuid1;// Calculated message length uint32 Length;// Calculated message hash uint32 Hash;}// Simple rejectmessageSimpleReject{// Reject Id uuid [id] = uuid1;// Error message string Error;}// Simple notificationmessageSimpleNotify{// Server notification string Notification;}// Disconnect request message[request]messageDisconnectRequest{// Request Id uuid [id] = uuid1;}
Here comes the example of the simple protocol server. It process clientrequests, answer with corresponding responses and send server notificationsback to clients.
usingSystem;usingSystem.Net;usingSystem.Net.Sockets;usingNetCoreServer;usingcom.chronoxor.simple;usingcom.chronoxor.simple.FBE;namespaceProtoServer{publicclassSimpleProtoSessionSender:Sender,ISenderListener{publicSimpleProtoSessionSession{get;}publicSimpleProtoSessionSender(SimpleProtoSessionsession){Session=session;}publiclongOnSend(byte[]buffer,longoffset,longsize){returnSession.SendAsync(buffer,offset,size)?size:0;}}publicclassSimpleProtoSessionReceiver:Receiver,IReceiverListener{publicSimpleProtoSessionSession{get;}publicSimpleProtoSessionReceiver(SimpleProtoSessionsession){Session=session;}publicvoidOnReceive(DisconnectRequestrequest){Session.OnReceive(request);}publicvoidOnReceive(SimpleRequestrequest){Session.OnReceive(request);}}publicclassSimpleProtoSession:TcpSession{publicSimpleProtoSessionSenderSender{get;}publicSimpleProtoSessionReceiverReceiver{get;}publicSimpleProtoSession(TcpServerserver):base(server){Sender=newSimpleProtoSessionSender(this);Receiver=newSimpleProtoSessionReceiver(this);}protectedoverridevoidOnConnected(){Console.WriteLine($"TCP protocol session with Id '{Id}' connected to remote address '{(Socket.RemoteEndPointasIPEndPoint)?.Address}' and port{(Socket.RemoteEndPointasIPEndPoint)?.Port}");// Send invite notificationSimpleNotifynotify=SimpleNotify.Default;notify.Notification="Hello from Simple protocol server! Please send a message or '!' to disconnect the client!";Sender.Send(notify);}protectedoverridevoidOnDisconnected(){Console.WriteLine($"TCP protocol session with Id '{Id}' disconnected");}protectedoverridevoidOnReceived(byte[]buffer,longoffset,longsize){Receiver.Receive(buffer,offset,size);}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"TCP protocol session with Id '{Id}' caught a socket error:{error}");}// Protocol handlerspublicvoidOnReceive(DisconnectRequestrequest){Disconnect();}publicvoidOnReceive(SimpleRequestrequest){Console.WriteLine($"Received:{request}");// Validate requestif(string.IsNullOrEmpty(request.Message)){// Send rejectSimpleRejectreject=SimpleReject.Default;reject.id=request.id;reject.Error="Request message is empty!";Sender.Send(reject);return;}// Send responseSimpleResponseresponse=SimpleResponse.Default;response.id=request.id;response.Hash=(uint)request.Message.GetHashCode();response.Length=(uint)request.Message.Length;Sender.Send(response);}}publicclassSimpleProtoSender:Sender,ISenderListener{publicSimpleProtoServerServer{get;}publicSimpleProtoSender(SimpleProtoServerserver){Server=server;}publiclongOnSend(byte[]buffer,longoffset,longsize){Server.Multicast(buffer,offset,size);returnsize;}}publicclassSimpleProtoServer:TcpServer{publicSimpleProtoSenderSender{get;}publicSimpleProtoServer(IPAddressaddress,intport):base(address,port){Sender=newSimpleProtoSender(this);}protectedoverrideTcpSessionCreateSession(){returnnewSimpleProtoSession(this);}protectedoverridevoidOnStarted(){Console.WriteLine($"Simple protocol server with Id '{Id}' started!");}protectedoverridevoidOnStopped(){Console.WriteLine($"Simple protocol server with Id '{Id}' stopped!");}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Simple protocol server with Id '{Id}' caught an error:{error}");}}classProgram{staticvoidMain(string[]args){// Simple protocol server portintport=4444;if(args.Length>0)port=int.Parse(args[0]);Console.WriteLine($"Simple protocol server port:{port}");Console.WriteLine();// Create a new simple protocol servervarserver=newSimpleProtoServer(IPAddress.Any,port);// Start the serverConsole.Write("Server starting...");server.Start();Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Restart the serverif(line=="!"){Console.Write("Server restarting...");server.Restart();Console.WriteLine("Done!");continue;}// Multicast admin notification to all sessionsSimpleNotifynotify=SimpleNotify.Default;notify.Notification="(admin) "+line;server.Sender.Send(notify);}// Stop the serverConsole.Write("Server stopping...");server.Stop();Console.WriteLine("Done!");}}}
Here comes the example of the simple protocol client. It connects to thesimple protocol server and allows to send requests to it and receivecorresponding responses.
usingSystem;usingSystem.Net.Sockets;usingSystem.Threading;usingTcpClient=NetCoreServer.TcpClient;usingcom.chronoxor.simple;usingcom.chronoxor.simple.FBE;namespaceProtoClient{publicclassTcpProtoClient:TcpClient{publicTcpProtoClient(stringaddress,intport):base(address,port){}publicboolConnectAndStart(){Console.WriteLine($"TCP protocol client starting a new session with Id '{Id}'...");StartReconnectTimer();returnConnectAsync();}publicboolDisconnectAndStop(){Console.WriteLine($"TCP protocol client stopping the session with Id '{Id}'...");StopReconnectTimer();DisconnectAsync();returntrue;}publicoverrideboolReconnect(){returnReconnectAsync();}privateTimer_reconnectTimer;publicvoidStartReconnectTimer(){// Start the reconnect timer_reconnectTimer=newTimer(state=>{Console.WriteLine($"TCP reconnect timer connecting the client session with Id '{Id}'...");ConnectAsync();},null,Timeout.InfiniteTimeSpan,Timeout.InfiniteTimeSpan);}publicvoidStopReconnectTimer(){// Stop the reconnect timer_reconnectTimer?.Dispose();_reconnectTimer=null;}publicdelegatevoidConnectedHandler();publiceventConnectedHandlerConnected=()=>{};protectedoverridevoidOnConnected(){Console.WriteLine($"TCP protocol client connected a new session with Id '{Id}' to remote address '{Address}' and port{Port}");Connected?.Invoke();}publicdelegatevoidDisconnectedHandler();publiceventDisconnectedHandlerDisconnected=()=>{};protectedoverridevoidOnDisconnected(){Console.WriteLine($"TCP protocol client disconnected the session with Id '{Id}'");// Setup and asynchronously wait for the reconnect timer_reconnectTimer?.Change(TimeSpan.FromSeconds(1),Timeout.InfiniteTimeSpan);Disconnected?.Invoke();}publicdelegatevoidReceivedHandler(byte[]buffer,longoffset,longsize);publiceventReceivedHandlerReceived=(buffer,offset,size)=>{};protectedoverridevoidOnReceived(byte[]buffer,longoffset,longsize){Received?.Invoke(buffer,offset,size);}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"TCP protocol client caught a socket error:{error}");} #region IDisposable implementation// Disposed flag.privatebool_disposed;protectedoverridevoidDispose(booldisposingManagedResources){if(!_disposed){if(disposingManagedResources){// Dispose managed resources here...StopReconnectTimer();}// Dispose unmanaged resources here...// Set large fields to null here...// Mark as disposed._disposed=true;}// Call Dispose in the base class.base.Dispose(disposingManagedResources);}// The derived class does not have a Finalize method// or a Dispose method without parameters because it inherits// them from the base class. #endregion}publicclassSimpleProtoClient:Client,ISenderListener,IReceiverListener,IDisposable{privatereadonlyTcpProtoClient_tcpProtoClient;publicGuidId=>_tcpProtoClient.Id;publicboolIsConnected=>_tcpProtoClient.IsConnected;publicSimpleProtoClient(stringaddress,intport){_tcpProtoClient=newTcpProtoClient(address,port);_tcpProtoClient.Connected+=OnConnected;_tcpProtoClient.Disconnected+=OnDisconnected;_tcpProtoClient.Received+=OnReceived;ReceivedResponse_DisconnectRequest+=HandleDisconnectRequest;ReceivedResponse_SimpleResponse+=HandleSimpleResponse;ReceivedResponse_SimpleReject+=HandleSimpleReject;ReceivedResponse_SimpleNotify+=HandleSimpleNotify;}privatevoidDisposeClient(){_tcpProtoClient.Connected-=OnConnected;_tcpProtoClient.Connected-=OnDisconnected;_tcpProtoClient.Received-=OnReceived;ReceivedResponse_DisconnectRequest-=HandleDisconnectRequest;ReceivedResponse_SimpleResponse-=HandleSimpleResponse;ReceivedResponse_SimpleReject-=HandleSimpleReject;ReceivedResponse_SimpleNotify-=HandleSimpleNotify;_tcpProtoClient.Dispose();}publicboolConnectAndStart(){return_tcpProtoClient.ConnectAndStart();}publicboolDisconnectAndStop(){return_tcpProtoClient.DisconnectAndStop();}publicboolReconnect(){return_tcpProtoClient.Reconnect();}privatebool_watchdog;privateThread_watchdogThread;publicboolStartWatchdog(){if(_watchdog)returnfalse;Console.WriteLine("Watchdog thread starting...");// Start the watchdog thread_watchdog=true;_watchdogThread=newThread(WatchdogThread);Console.WriteLine("Watchdog thread started!");returntrue;}publicboolStopWatchdog(){if(!_watchdog)returnfalse;Console.WriteLine("Watchdog thread stopping...");// Stop the watchdog thread_watchdog=false;_watchdogThread.Join();Console.WriteLine("Watchdog thread stopped!");returntrue;}publicstaticvoidWatchdogThread(objectobj){varinstance=objasSimpleProtoClient;if(instance==null)return;try{// Watchdog loop...while(instance._watchdog){varutc=DateTime.UtcNow;// Watchdog the clientinstance.Watchdog(utc);// Sleep for a while...Thread.Sleep(1000);}}catch(Exceptione){Console.WriteLine($"Config client watchdog thread terminated:{e}");}} #region Connection handlerspublicdelegatevoidConnectedHandler();publiceventConnectedHandlerConnected=()=>{};privatevoidOnConnected(){// Reset FBE protocol buffersReset();Connected?.Invoke();}publicdelegatevoidDisconnectedHandler();publiceventDisconnectedHandlerDisconnected=()=>{};privatevoidOnDisconnected(){Disconnected?.Invoke();}publiclongOnSend(byte[]buffer,longoffset,longsize){return_tcpProtoClient.SendAsync(buffer,offset,size)?size:0;}publicvoidOnReceived(byte[]buffer,longoffset,longsize){Receive(buffer,offset,size);} #endregion #region Protocol handlersprivatevoidHandleDisconnectRequest(DisconnectRequestrequest){Console.WriteLine($"Received:{request}");_tcpProtoClient.DisconnectAsync();}privatevoidHandleSimpleResponse(SimpleResponseresponse){Console.WriteLine($"Received:{response}");}privatevoidHandleSimpleReject(SimpleRejectreject){Console.WriteLine($"Received:{reject}");}privatevoidHandleSimpleNotify(SimpleNotifynotify){Console.WriteLine($"Received:{notify}");} #endregion #region IDisposable implementation// Disposed flag.privatebool_disposed;// Implement IDisposable.publicvoidDispose(){Dispose(true);GC.SuppressFinalize(this);}protectedvirtualvoidDispose(booldisposingManagedResources){// The idea here is that Dispose(Boolean) knows whether it is// being called to do explicit cleanup (the Boolean is true)// versus being called due to a garbage collection (the Boolean// is false). This distinction is useful because, when being// disposed explicitly, the Dispose(Boolean) method can safely// execute code using reference type fields that refer to other// objects knowing for sure that these other objects have not been// finalized or disposed of yet. When the Boolean is false,// the Dispose(Boolean) method should not execute code that// refer to reference type fields because those objects may// have already been finalized."if(!_disposed){if(disposingManagedResources){// Dispose managed resources here...DisposeClient();}// Dispose unmanaged resources here...// Set large fields to null here...// Mark as disposed._disposed=true;}} #endregion}classProgram{staticvoidMain(string[]args){// Simple protocol server addressstringaddress="127.0.0.1";if(args.Length>0)address=args[0];// Simple protocol server portintport=4444;if(args.Length>1)port=int.Parse(args[1]);Console.WriteLine($"Simple protocol server address:{address}");Console.WriteLine($"Simple protocol server port:{port}");Console.WriteLine();// Create a new simple protocol chat clientvarclient=newSimpleProtoClient(address,port);// Connect the clientConsole.Write("Client connecting...");client.ConnectAndStart();Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Disconnect the clientif(line=="!"){Console.Write("Client disconnecting...");client.Reconnect();Console.WriteLine("Done!");continue;}// Send request to the simple protocol serverSimpleRequestrequest=SimpleRequest.Default;request.Message=line;varresponse=client.Request(request).Result;// Show string hash calculation resultConsole.WriteLine($"Hash of '{line}' = 0x{response.Hash:X8}");}// Disconnect the clientConsole.Write("Client disconnecting...");client.DisconnectAndStop();Console.WriteLine("Done!");}}}
Here comes the example of the HTTP cache server. It allows to manipulatecache data with HTTP methods (GET, POST, PUT and DELETE).
Use the following link to openSwagger OpenAPI iterative documentation:http://localhost:8080/api/index.html
usingSystem;usingSystem.Collections.Concurrent;usingSystem.Net;usingSystem.Net.Sockets;usingSystem.Text;usingNetCoreServer;namespaceHttpServer{classCommonCache{publicstaticCommonCacheGetInstance(){if(_instance==null)_instance=newCommonCache();return_instance;}publicstringGetAllCache(){varresult=newStringBuilder();result.Append("[\n");foreach(varitemin_cache){result.Append(" {\n");result.AppendFormat($"\"key\":\"{item.Key}\",\n");result.AppendFormat($"\"value\":\"{item.Value}\",\n");result.Append(" },\n");}result.Append("]\n");returnresult.ToString();}publicboolGetCacheValue(stringkey,outstringvalue){return_cache.TryGetValue(key,outvalue);}publicvoidPutCacheValue(stringkey,stringvalue){_cache[key]=value;}publicboolDeleteCacheValue(stringkey,outstringvalue){return_cache.TryRemove(key,outvalue);}privatereadonlyConcurrentDictionary<string,string>_cache=newConcurrentDictionary<string,string>();privatestaticCommonCache_instance;}classHttpCacheSession:HttpSession{publicHttpCacheSession(NetCoreServer.HttpServerserver):base(server){}protectedoverridevoidOnReceivedRequest(HttpRequestrequest){// Show HTTP request contentConsole.WriteLine(request);// Process HTTP request methodsif(request.Method=="HEAD")SendResponseAsync(Response.MakeHeadResponse());elseif(request.Method=="GET"){stringkey=request.Url;// Decode the key valuekey=Uri.UnescapeDataString(key);key=key.Replace("/api/cache","",StringComparison.InvariantCultureIgnoreCase);key=key.Replace("?key=","",StringComparison.InvariantCultureIgnoreCase);if(string.IsNullOrEmpty(key)){// Response with all cache valuesSendResponseAsync(Response.MakeGetResponse(CommonCache.GetInstance().GetAllCache(),"application/json; charset=UTF-8"));}// Get the cache value by the given keyelseif(CommonCache.GetInstance().GetCacheValue(key,outvarvalue)){// Response with the cache valueSendResponseAsync(Response.MakeGetResponse(value));}elseSendResponseAsync(Response.MakeErrorResponse(404,"Required cache value was not found for the key: "+key));}elseif((request.Method=="POST")||(request.Method=="PUT")){stringkey=request.Url;stringvalue=request.Body;// Decode the key valuekey=Uri.UnescapeDataString(key);key=key.Replace("/api/cache","",StringComparison.InvariantCultureIgnoreCase);key=key.Replace("?key=","",StringComparison.InvariantCultureIgnoreCase);// Put the cache valueCommonCache.GetInstance().PutCacheValue(key,value);// Response with the cache valueSendResponseAsync(Response.MakeOkResponse());}elseif(request.Method=="DELETE"){stringkey=request.Url;// Decode the key valuekey=Uri.UnescapeDataString(key);key=key.Replace("/api/cache","",StringComparison.InvariantCultureIgnoreCase);key=key.Replace("?key=","",StringComparison.InvariantCultureIgnoreCase);// Delete the cache valueif(CommonCache.GetInstance().DeleteCacheValue(key,outvarvalue)){// Response with the cache valueSendResponseAsync(Response.MakeGetResponse(value));}elseSendResponseAsync(Response.MakeErrorResponse(404,"Deleted cache value was not found for the key: "+key));}elseif(request.Method=="OPTIONS")SendResponseAsync(Response.MakeOptionsResponse());elseif(request.Method=="TRACE")SendResponseAsync(Response.MakeTraceResponse(request.Cache.Data));elseSendResponseAsync(Response.MakeErrorResponse("Unsupported HTTP method: "+request.Method));}protectedoverridevoidOnReceivedRequestError(HttpRequestrequest,stringerror){Console.WriteLine($"Request error:{error}");}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"HTTP session caught an error:{error}");}}classHttpCacheServer:NetCoreServer.HttpServer{publicHttpCacheServer(IPAddressaddress,intport):base(address,port){}protectedoverrideTcpSessionCreateSession(){returnnewHttpCacheSession(this);}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"HTTP session caught an error:{error}");}}classProgram{staticvoidMain(string[]args){// HTTP server portintport=8080;if(args.Length>0)port=int.Parse(args[0]);// HTTP server content pathstringwww="../../../../../www/api";if(args.Length>1)www=args[1];Console.WriteLine($"HTTP server port:{port}");Console.WriteLine($"HTTP server static content path:{www}");Console.WriteLine($"HTTP server website: http://localhost:{port}/api/index.html");Console.WriteLine();// Create a new HTTP servervarserver=newHttpCacheServer(IPAddress.Any,port);server.AddStaticContent(www,"/api");// Start the serverConsole.Write("Server starting...");server.Start();Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Restart the serverif(line=="!"){Console.Write("Server restarting...");server.Restart();Console.WriteLine("Done!");}}// Stop the serverConsole.Write("Server stopping...");server.Stop();Console.WriteLine("Done!");}}}
Here comes the example of the HTTP client. It allows to send HTTP requests(GET, POST, PUT and DELETE) and receive HTTP responses.
usingSystem;usingNetCoreServer;namespaceHttpClient{classProgram{staticvoidMain(string[]args){// HTTP server addressstringaddress="127.0.0.1";if(args.Length>0)address=args[0];// HTTP server portintport=8080;if(args.Length>1)port=int.Parse(args[1]);Console.WriteLine($"HTTP server address:{address}");Console.WriteLine($"HTTP server port:{port}");Console.WriteLine();// Create a new HTTP clientvarclient=newHttpClientEx(address,port);Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Reconnect the clientif(line=="!"){Console.Write("Client reconnecting...");if(client.IsConnected)client.ReconnectAsync();elseclient.ConnectAsync();Console.WriteLine("Done!");continue;}varcommands=line.Split(' ');if(commands.Length<2){Console.WriteLine("HTTP method and URL must be entered!");continue;}if(commands[0].ToUpper()=="HEAD"){varresponse=client.SendHeadRequest(commands[1]).Result;Console.WriteLine(response);}elseif(commands[0].ToUpper()=="GET"){varresponse=client.SendGetRequest(commands[1]).Result;Console.WriteLine(response);}elseif(commands[0].ToUpper()=="POST"){if(commands.Length<3){Console.WriteLine("HTTP method, URL and body must be entered!");continue;}varresponse=client.SendPostRequest(commands[1],commands[2]).Result;Console.WriteLine(response);}elseif(commands[0].ToUpper()=="PUT"){if(commands.Length<3){Console.WriteLine("HTTP method, URL and body must be entered!");continue;}varresponse=client.SendPutRequest(commands[1],commands[2]).Result;Console.WriteLine(response);}elseif(commands[0].ToUpper()=="DELETE"){varresponse=client.SendDeleteRequest(commands[1]).Result;Console.WriteLine(response);}elseif(commands[0].ToUpper()=="OPTIONS"){varresponse=client.SendOptionsRequest(commands[1]).Result;Console.WriteLine(response);}elseif(commands[0].ToUpper()=="TRACE"){varresponse=client.SendTraceRequest(commands[1]).Result;Console.WriteLine(response);}elseConsole.WriteLine("Unknown HTTP method");}// Disconnect the clientConsole.Write("Client disconnecting...");client.Disconnect();Console.WriteLine("Done!");}}}
Here comes the example of the HTTPS cache server. It allows to manipulatecache data with HTTP methods (GET, POST, PUT and DELETE) with securedtransport protocol.
Use the following link to openSwagger OpenAPI iterative documentation:https://localhost:8443/api/index.html
usingSystem;usingSystem.Collections.Concurrent;usingSystem.Net;usingSystem.Net.Sockets;usingSystem.Security.Authentication;usingSystem.Security.Cryptography.X509Certificates;usingSystem.Text;usingNetCoreServer;namespaceHttpsServer{classCommonCache{publicstaticCommonCacheGetInstance(){if(_instance==null)_instance=newCommonCache();return_instance;}publicstringGetAllCache(){varresult=newStringBuilder();result.Append("[\n");foreach(varitemin_cache){result.Append(" {\n");result.AppendFormat($"\"key\":\"{item.Key}\",\n");result.AppendFormat($"\"value\":\"{item.Value}\",\n");result.Append(" },\n");}result.Append("]\n");returnresult.ToString();}publicboolGetCacheValue(stringkey,outstringvalue){return_cache.TryGetValue(key,outvalue);}publicvoidPutCacheValue(stringkey,stringvalue){_cache[key]=value;}publicboolDeleteCacheValue(stringkey,outstringvalue){return_cache.TryRemove(key,outvalue);}privatereadonlyConcurrentDictionary<string,string>_cache=newConcurrentDictionary<string,string>();privatestaticCommonCache_instance;}classHttpsCacheSession:HttpsSession{publicHttpsCacheSession(NetCoreServer.HttpsServerserver):base(server){}protectedoverridevoidOnReceivedRequest(HttpRequestrequest){// Show HTTP request contentConsole.WriteLine(request);// Process HTTP request methodsif(request.Method=="HEAD")SendResponseAsync(Response.MakeHeadResponse());elseif(request.Method=="GET"){stringkey=request.Url;// Decode the key valuekey=Uri.UnescapeDataString(key);key=key.Replace("/api/cache","",StringComparison.InvariantCultureIgnoreCase);key=key.Replace("?key=","",StringComparison.InvariantCultureIgnoreCase);if(string.IsNullOrEmpty(key)){// Response with all cache valuesSendResponseAsync(Response.MakeGetResponse(CommonCache.GetInstance().GetAllCache(),"application/json; charset=UTF-8"));}// Get the cache value by the given keyelseif(CommonCache.GetInstance().GetCacheValue(key,outvarvalue)){// Response with the cache valueSendResponseAsync(Response.MakeGetResponse(value));}elseSendResponseAsync(Response.MakeErrorResponse(404,"Required cache value was not found for the key: "+key));}elseif((request.Method=="POST")||(request.Method=="PUT")){stringkey=request.Url;stringvalue=request.Body;// Decode the key valuekey=Uri.UnescapeDataString(key);key=key.Replace("/api/cache","",StringComparison.InvariantCultureIgnoreCase);key=key.Replace("?key=","",StringComparison.InvariantCultureIgnoreCase);// Put the cache valueCommonCache.GetInstance().PutCacheValue(key,value);// Response with the cache valueSendResponseAsync(Response.MakeOkResponse());}elseif(request.Method=="DELETE"){stringkey=request.Url;// Decode the key valuekey=Uri.UnescapeDataString(key);key=key.Replace("/api/cache","",StringComparison.InvariantCultureIgnoreCase);key=key.Replace("?key=","",StringComparison.InvariantCultureIgnoreCase);// Delete the cache valueif(CommonCache.GetInstance().DeleteCacheValue(key,outvarvalue)){// Response with the cache valueSendResponseAsync(Response.MakeGetResponse(value));}elseSendResponseAsync(Response.MakeErrorResponse(404,"Deleted cache value was not found for the key: "+key));}elseif(request.Method=="OPTIONS")SendResponseAsync(Response.MakeOptionsResponse());elseif(request.Method=="TRACE")SendResponseAsync(Response.MakeTraceResponse(request.Cache));elseSendResponseAsync(Response.MakeErrorResponse("Unsupported HTTP method: "+request.Method));}protectedoverridevoidOnReceivedRequestError(HttpRequestrequest,stringerror){Console.WriteLine($"Request error:{error}");}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"HTTPS session caught an error:{error}");}}classHttpsCacheServer:NetCoreServer.HttpsServer{publicHttpsCacheServer(SslContextcontext,IPAddressaddress,intport):base(context,address,port){}protectedoverrideSslSessionCreateSession(){returnnewHttpsCacheSession(this);}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"HTTPS server caught an error:{error}");}}classProgram{staticvoidMain(string[]args){// HTTPS server portintport=8443;if(args.Length>0)port=int.Parse(args[0]);// HTTPS server content pathstringwww="../../../../../www/api";if(args.Length>1)www=args[1];Console.WriteLine($"HTTPS server port:{port}");Console.WriteLine($"HTTPS server static content path:{www}");Console.WriteLine($"HTTPS server website: https://localhost:{port}/api/index.html");Console.WriteLine();// Create and prepare a new SSL server contextvarcontext=newSslContext(SslProtocols.Tls12,newX509Certificate2("server.pfx","qwerty"));// Create a new HTTP servervarserver=newHttpsCacheServer(context,IPAddress.Any,port);server.AddStaticContent(www,"/api");// Start the serverConsole.Write("Server starting...");server.Start();Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Restart the serverif(line=="!"){Console.Write("Server restarting...");server.Restart();Console.WriteLine("Done!");}}// Stop the serverConsole.Write("Server stopping...");server.Stop();Console.WriteLine("Done!");}}}
Here comes the example of the HTTPS client. It allows to send HTTP requests(GET, POST, PUT and DELETE) and receive HTTP responses with securedtransport protocol.
usingSystem;usingSystem.Security.Authentication;usingSystem.Security.Cryptography.X509Certificates;usingNetCoreServer;namespaceHttpsClient{classProgram{staticvoidMain(string[]args){// HTTPS server addressstringaddress="127.0.0.1";if(args.Length>0)address=args[0];// HTTPS server portintport=8443;if(args.Length>1)port=int.Parse(args[1]);Console.WriteLine($"HTTPS server address:{address}");Console.WriteLine($"HTTPS server port:{port}");Console.WriteLine();// Create and prepare a new SSL client contextvarcontext=newSslContext(SslProtocols.Tls12,newX509Certificate2("client.pfx","qwerty"),(sender,certificate,chain,sslPolicyErrors)=>true);// Create a new HTTPS clientvarclient=newHttpsClientEx(context,address,port);Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Reconnect the clientif(line=="!"){Console.Write("Client reconnecting...");if(client.IsConnected)client.ReconnectAsync();elseclient.ConnectAsync();Console.WriteLine("Done!");continue;}varcommands=line.Split(' ');if(commands.Length<2){Console.WriteLine("HTTP method and URL must be entered!");continue;}if(commands[0].ToUpper()=="HEAD"){varresponse=client.SendHeadRequest(commands[1]).Result;Console.WriteLine(response);}elseif(commands[0].ToUpper()=="GET"){varresponse=client.SendGetRequest(commands[1]).Result;Console.WriteLine(response);}elseif(commands[0].ToUpper()=="POST"){if(commands.Length<3){Console.WriteLine("HTTP method, URL and body must be entered!");continue;}varresponse=client.SendPostRequest(commands[1],commands[2]).Result;Console.WriteLine(response);}elseif(commands[0].ToUpper()=="PUT"){if(commands.Length<3){Console.WriteLine("HTTP method, URL and body must be entered!");continue;}varresponse=client.SendPutRequest(commands[1],commands[2]).Result;Console.WriteLine(response);}elseif(commands[0].ToUpper()=="DELETE"){varresponse=client.SendDeleteRequest(commands[1]).Result;Console.WriteLine(response);}elseif(commands[0].ToUpper()=="OPTIONS"){varresponse=client.SendOptionsRequest(commands[1]).Result;Console.WriteLine(response);}elseif(commands[0].ToUpper()=="TRACE"){varresponse=client.SendTraceRequest(commands[1]).Result;Console.WriteLine(response);}elseConsole.WriteLine("Unknown HTTP method");}// Disconnect the clientConsole.Write("Client disconnecting...");client.Disconnect();Console.WriteLine("Done!");}}}
Here comes the example of the WebSocket chat server. It handles multipleWebSocket client sessions and multicast received message from any sessionto all ones. Also it is possible to send admin message directly from theserver.
Use the following link to open WebSocket chat server example:http://localhost:8080/chat/index.html
usingSystem;usingSystem.Net;usingSystem.Net.Sockets;usingSystem.Text;usingNetCoreServer;namespaceWsChatServer{classChatSession:WsSession{publicChatSession(WsServerserver):base(server){}publicoverridevoidOnWsConnected(HttpRequestrequest){Console.WriteLine($"Chat WebSocket session with Id{Id} connected!");// Send invite messagestringmessage="Hello from WebSocket chat! Please send a message or '!' to disconnect the client!";SendTextAsync(message);}publicoverridevoidOnWsDisconnected(){Console.WriteLine($"Chat WebSocket session with Id{Id} disconnected!");}publicoverridevoidOnWsReceived(byte[]buffer,longoffset,longsize){stringmessage=Encoding.UTF8.GetString(buffer,(int)offset,(int)size);Console.WriteLine("Incoming: "+message);// Multicast message to all connected sessions((WsServer)Server).MulticastText(message);// If the buffer starts with '!' the disconnect the current sessionif(message=="!")Close(1000);}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Chat WebSocket session caught an error with code{error}");}}classChatServer:WsServer{publicChatServer(IPAddressaddress,intport):base(address,port){}protectedoverrideTcpSessionCreateSession(){returnnewChatSession(this);}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Chat WebSocket server caught an error with code{error}");}}classProgram{staticvoidMain(string[]args){// WebSocket server portintport=8080;if(args.Length>0)port=int.Parse(args[0]);// WebSocket server content pathstringwww="../../../../../www/ws";if(args.Length>1)www=args[1];Console.WriteLine($"WebSocket server port:{port}");Console.WriteLine($"WebSocket server static content path:{www}");Console.WriteLine($"WebSocket server website: http://localhost:{port}/chat/index.html");Console.WriteLine();// Create a new WebSocket servervarserver=newChatServer(IPAddress.Any,port);server.AddStaticContent(www,"/chat");// Start the serverConsole.Write("Server starting...");server.Start();Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Restart the serverif(line=="!"){Console.Write("Server restarting...");server.Restart();Console.WriteLine("Done!");}// Multicast admin message to all sessionsline="(admin) "+line;server.MulticastText(line);}// Stop the serverConsole.Write("Server stopping...");server.Stop();Console.WriteLine("Done!");}}}
Here comes the example of the WebSocket chat client. It connects to theWebSocket chat server and allows to send message to it and receive newmessages.
usingSystem;usingSystem.Net.Sockets;usingSystem.Text;usingSystem.Threading;usingNetCoreServer;namespaceWsChatClient{classChatClient:WsClient{publicChatClient(stringaddress,intport):base(address,port){}publicvoidDisconnectAndStop(){_stop=true;CloseAsync(1000);while(IsConnected)Thread.Yield();}publicoverridevoidOnWsConnecting(HttpRequestrequest){request.SetBegin("GET","/");request.SetHeader("Host","localhost");request.SetHeader("Origin","http://localhost");request.SetHeader("Upgrade","websocket");request.SetHeader("Connection","Upgrade");request.SetHeader("Sec-WebSocket-Key",Convert.ToBase64String(WsNonce));request.SetHeader("Sec-WebSocket-Protocol","chat, superchat");request.SetHeader("Sec-WebSocket-Version","13");request.SetBody();}publicoverridevoidOnWsConnected(HttpResponseresponse){Console.WriteLine($"Chat WebSocket client connected a new session with Id{Id}");}publicoverridevoidOnWsDisconnected(){Console.WriteLine($"Chat WebSocket client disconnected a session with Id{Id}");}publicoverridevoidOnWsReceived(byte[]buffer,longoffset,longsize){Console.WriteLine($"Incoming:{Encoding.UTF8.GetString(buffer,(int)offset,(int)size)}");}protectedoverridevoidOnDisconnected(){base.OnDisconnected();Console.WriteLine($"Chat WebSocket client disconnected a session with Id{Id}");// Wait for a while...Thread.Sleep(1000);// Try to connect againif(!_stop)ConnectAsync();}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Chat WebSocket client caught an error with code{error}");}privatebool_stop;}classProgram{staticvoidMain(string[]args){// WebSocket server addressstringaddress="127.0.0.1";if(args.Length>0)address=args[0];// WebSocket server portintport=8080;if(args.Length>1)port=int.Parse(args[1]);Console.WriteLine($"WebSocket server address:{address}");Console.WriteLine($"WebSocket server port:{port}");Console.WriteLine();// Create a new TCP chat clientvarclient=newChatClient(address,port);// Connect the clientConsole.Write("Client connecting...");client.ConnectAsync();Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Disconnect the clientif(line=="!"){Console.Write("Client disconnecting...");client.DisconnectAsync();Console.WriteLine("Done!");continue;}// Send the entered text to the chat serverclient.SendTextAsync(line);}// Disconnect the clientConsole.Write("Client disconnecting...");client.DisconnectAndStop();Console.WriteLine("Done!");}}}
Here comes the example of the WebSocket secure chat server. It handlesmultiple WebSocket secure client sessions and multicast received messagefrom any session to all ones. Also it is possible to send admin messagedirectly from the server.
This example is very similar to the WebSocket one except the code thatprepares WebSocket secure context and handshake handler.
Use the following link to open WebSocket secure chat server example:https://localhost:8443/chat/index.html
usingSystem;usingSystem.Net;usingSystem.Net.Sockets;usingSystem.Security.Authentication;usingSystem.Security.Cryptography.X509Certificates;usingSystem.Text;usingNetCoreServer;namespaceWssChatServer{classChatSession:WssSession{publicChatSession(WssServerserver):base(server){}publicoverridevoidOnWsConnected(HttpRequestrequest){Console.WriteLine($"Chat WebSocket session with Id{Id} connected!");// Send invite messagestringmessage="Hello from WebSocket chat! Please send a message or '!' to disconnect the client!";SendTextAsync(message);}publicoverridevoidOnWsDisconnected(){Console.WriteLine($"Chat WebSocket session with Id{Id} disconnected!");}publicoverridevoidOnWsReceived(byte[]buffer,longoffset,longsize){stringmessage=Encoding.UTF8.GetString(buffer,(int)offset,(int)size);Console.WriteLine("Incoming: "+message);// Multicast message to all connected sessions((WssServer)Server).MulticastText(message);// If the buffer starts with '!' the disconnect the current sessionif(message=="!")Close(1000);}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Chat WebSocket session caught an error with code{error}");}}classChatServer:WssServer{publicChatServer(SslContextcontext,IPAddressaddress,intport):base(context,address,port){}protectedoverrideSslSessionCreateSession(){returnnewChatSession(this);}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Chat WebSocket server caught an error with code{error}");}}classProgram{staticvoidMain(string[]args){// WebSocket server portintport=8443;if(args.Length>0)port=int.Parse(args[0]);// WebSocket server content pathstringwww="../../../../../www/wss";if(args.Length>1)www=args[1];Console.WriteLine($"WebSocket server port:{port}");Console.WriteLine($"WebSocket server static content path:{www}");Console.WriteLine($"WebSocket server website: https://localhost:{port}/chat/index.html");Console.WriteLine();// Create and prepare a new SSL server contextvarcontext=newSslContext(SslProtocols.Tls12,newX509Certificate2("server.pfx","qwerty"));// Create a new WebSocket servervarserver=newChatServer(context,IPAddress.Any,port);server.AddStaticContent(www,"/chat");// Start the serverConsole.Write("Server starting...");server.Start();Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Restart the serverif(line=="!"){Console.Write("Server restarting...");server.Restart();Console.WriteLine("Done!");}// Multicast admin message to all sessionsline="(admin) "+line;server.MulticastText(line);}// Stop the serverConsole.Write("Server stopping...");server.Stop();Console.WriteLine("Done!");}}}
Here comes the example of the WebSocket secure chat client. It connects tothe WebSocket secure chat server and allows to send message to it and receivenew messages.
This example is very similar to the WebSocket one except the code thatprepares WebSocket secure context and handshake handler.
usingSystem;usingSystem.Net.Sockets;usingSystem.Security.Authentication;usingSystem.Security.Cryptography.X509Certificates;usingSystem.Text;usingSystem.Threading;usingNetCoreServer;namespaceWssChatClient{classChatClient:WssClient{publicChatClient(SslContextcontext,stringaddress,intport):base(context,address,port){}publicvoidDisconnectAndStop(){_stop=true;CloseAsync(1000);while(IsConnected)Thread.Yield();}publicoverridevoidOnWsConnecting(HttpRequestrequest){request.SetBegin("GET","/");request.SetHeader("Host","localhost");request.SetHeader("Origin","http://localhost");request.SetHeader("Upgrade","websocket");request.SetHeader("Connection","Upgrade");request.SetHeader("Sec-WebSocket-Key",Convert.ToBase64String(WsNonce));request.SetHeader("Sec-WebSocket-Protocol","chat, superchat");request.SetHeader("Sec-WebSocket-Version","13");request.SetBody();}publicoverridevoidOnWsConnected(HttpResponseresponse){Console.WriteLine($"Chat WebSocket client connected a new session with Id{Id}");}publicoverridevoidOnWsDisconnected(){Console.WriteLine($"Chat WebSocket client disconnected a session with Id{Id}");}publicoverridevoidOnWsReceived(byte[]buffer,longoffset,longsize){Console.WriteLine($"Incoming:{Encoding.UTF8.GetString(buffer,(int)offset,(int)size)}");}protectedoverridevoidOnDisconnected(){base.OnDisconnected();Console.WriteLine($"Chat WebSocket client disconnected a session with Id{Id}");// Wait for a while...Thread.Sleep(1000);// Try to connect againif(!_stop)ConnectAsync();}protectedoverridevoidOnError(SocketErrorerror){Console.WriteLine($"Chat WebSocket client caught an error with code{error}");}privatebool_stop;}classProgram{staticvoidMain(string[]args){// WebSocket server addressstringaddress="127.0.0.1";if(args.Length>0)address=args[0];// WebSocket server portintport=8443;if(args.Length>1)port=int.Parse(args[1]);Console.WriteLine($"WebSocket server address:{address}");Console.WriteLine($"WebSocket server port:{port}");Console.WriteLine();// Create and prepare a new SSL client contextvarcontext=newSslContext(SslProtocols.Tls12,newX509Certificate2("client.pfx","qwerty"),(sender,certificate,chain,sslPolicyErrors)=>true);// Create a new TCP chat clientvarclient=newChatClient(context,address,port);// Connect the clientConsole.Write("Client connecting...");client.ConnectAsync();Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");// Perform text inputfor(;;){stringline=Console.ReadLine();if(string.IsNullOrEmpty(line))break;// Reconnect the clientif(line=="!"){Console.Write("Client reconnecting...");if(client.IsConnected)client.ReconnectAsync();elseclient.ConnectAsync();Console.WriteLine("Done!");continue;}// Send the entered text to the chat serverclient.SendTextAsync(line);}// Disconnect the clientConsole.Write("Client disconnecting...");client.DisconnectAndStop();Console.WriteLine("Done!");}}}
Here comes several communication scenarios with timing measurements.
Benchmark environment is the following:
CPU architecutre: Intel(R) Core(TM) i7-4790K CPU @ 4.00GHzCPU logical cores: 8CPU physical cores: 4CPU clock speed: 3.998 GHzCPU Hyper-Threading: enabledRAM total: 31.962 GiBRAM free: 24.011 GiBOS version: Microsoft Windows 8 Enterprise Edition (build 9200), 64-bitOS bits: 64-bitProcess bits: 64-bitProcess configuaraion: release
This scenario sends lots of messages from several clients to a server.The server responses to each message and resend the similar response tothe client. The benchmark measures total round-trip time to send allmessages and receive all responses, messages & data throughput, countof errors.
- TcpEchoServer
- TcpEchoClient --clients 1
Server address: 127.0.0.1Server port: 1111Working clients: 1Working messages: 1000Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.024 sTotal data: 2.831 GiBTotal messages: 94369133Data throughput: 287.299 MiB/sMessage latency: 106 nsMessage throughput: 9413997 msg/s
- TcpEchoServer
- TcpEchoClient --clients 100
Server address: 127.0.0.1Server port: 1111Working clients: 100Working messages: 1000Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.189 sTotal data: 1.794 GiBTotal messages: 59585544Data throughput: 178.463 MiB/sMessage latency: 171 nsMessage throughput: 5847523 msg/s
- SslEchoServer
- SslEchoClient --clients 1
Server address: 127.0.0.1Server port: 2222Working clients: 1Working messages: 1000Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 2.645 sTotal data: 373.329 MiBTotal messages: 12233021Data throughput: 141.095 MiB/sMessage latency: 216 nsMessage throughput: 4623352 msg/s
- SslEchoServer
- SslEchoClient --clients 100
Server address: 127.0.0.1Server port: 2222Working clients: 100Working messages: 1000Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.060 sTotal data: 1.472 GiBTotal messages: 49029133Data throughput: 148.741 MiB/sMessage latency: 205 nsMessage throughput: 4873398 msg/s
- UdpEchoServer
- UdpEchoClient --clients 1
Server address: 127.0.0.1Server port: 3333Working clients: 1Working messages: 1000Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.032 sTotal data: 33.994 MiBTotal messages: 1113182Data throughput: 3.395 MiB/sMessage latency: 9.012 mcsMessage throughput: 110960 msg/s
- UdpEchoServer
- UdpEchoClient --clients 100
Server address: 127.0.0.1Server port: 3333Working clients: 100Working messages: 1000Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.635 sTotal data: 20.355 MiBTotal messages: 666791Data throughput: 1.934 MiB/sMessage latency: 15.950 mcsMessage throughput: 62693 msg/s
- UdsEchoServer
- UdsEchoClient --clients 1
Server Unix Domain Socket path: C:\Users\chronoxor\AppData\Local\Temp\echo.sockWorking clients: 1Working messages: 1000Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.016 sTotal data: 208.657 MiBTotal messages: 6836769Data throughput: 20.850 MiB/sMessage latency: 1.465 mcsMessage throughput: 682575 msg/s
- UdsEchoServer
- UdsEchoClient --clients 100
Server Unix Domain Socket path: C:\Users\chronoxor\AppData\Local\Temp\echo.sockWorking clients: 100Working messages: 1000Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 12.253 sTotal data: 602.320 MiBTotal messages: 19736578Data throughput: 49.157 MiB/sMessage latency: 620 nsMessage throughput: 1610666 msg/s
- ProtoServer
- ProtoClient --clients 1
Server address: 127.0.0.1Server port: 4444Working clients: 1Working messages: 1000Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.015 sTotal data: 100.568 MiBTotal messages: 3294993Data throughput: 10.040 MiB/sMessage latency: 3.039 mcsMessage throughput: 328978 msg/s
- ProtoServer
- ProtoClient --clients 100
Server address: 127.0.0.1Server port: 4444Working clients: 100Working messages: 1000Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 12.530 sTotal data: 207.994 MiBTotal messages: 6814785Data throughput: 16.611 MiB/sMessage latency: 1.838 mcsMessage throughput: 543858 msg/s
- WsEchoServer
- WsEchoClient --clients 1
Server address: 127.0.0.1Server port: 8080Working clients: 1Working messages: 1000Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 3.037 sTotal data: 105.499 MiBTotal messages: 3456618Data throughput: 34.742 MiB/sMessage latency: 878 nsMessage throughput: 1137864 msg/s
- WsEchoServer
- WsEchoClient --clients 100
Server address: 127.0.0.1Server port: 8080Working clients: 100Working messages: 1000Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.078 sTotal data: 426.803 MiBTotal messages: 13984888Data throughput: 42.353 MiB/sMessage latency: 720 nsMessage throughput: 1387555 msg/s
- WssEchoServer
- WssEchoClient --clients 1
Server address: 127.0.0.1Server port: 8443Working clients: 1Working messages: 1000Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.030 sTotal data: 198.103 MiBTotal messages: 6491390Data throughput: 19.767 MiB/sMessage latency: 1.545 mcsMessage throughput: 647153 msg/s
- WssEchoServer
- WssEchoClient --clients 100
Server address: 127.0.0.1Server port: 8443Working clients: 100Working messages: 1000Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.112 sTotal data: 405.286 MiBTotal messages: 13280221Data throughput: 40.078 MiB/sMessage latency: 761 nsMessage throughput: 1313228 msg/s
In this scenario server multicasts messages to all connected clients.The benchmark counts total messages received by all clients for allthe working time and measures messages & data throughput, countof errors.
- TcpMulticastServer
- TcpMulticastClient --clients 1
Server address: 127.0.0.1Server port: 1111Working clients: 1Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.022 sTotal data: 407.023 MiBTotal messages: 13337326Data throughput: 40.625 MiB/sMessage latency: 751 nsMessage throughput: 1330734 msg/s
- TcpMulticastServer
- TcpMulticastClient --clients 100
Server address: 127.0.0.1Server port: 1111Working clients: 100Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.112 sTotal data: 421.348 MiBTotal messages: 13806493Data throughput: 41.681 MiB/sMessage latency: 732 nsMessage throughput: 1365280 msg/s
- SslMulticastServer
- SslMulticastClient --clients 1
Server address: 127.0.0.1Server port: 2222Working clients: 1Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.024 sTotal data: 325.225 MiBTotal messages: 10656801Data throughput: 32.453 MiB/sMessage latency: 940 nsMessage throughput: 1063075 msg/s
- SslMulticastServer
- SslMulticastClient --clients 100
Server address: 127.0.0.1Server port: 2222Working clients: 100Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.144 sTotal data: 343.460 MiBTotal messages: 11254173Data throughput: 33.876 MiB/sMessage latency: 901 nsMessage throughput: 1109393 msg/s
- UdpMulticastServer
- UdpMulticastClient --clients 1
Server address: 239.255.0.1Server port: 3333Working clients: 1Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.026 sTotal data: 13.225 MiBTotal messages: 433202Data throughput: 1.326 MiB/sMessage latency: 23.145 mcsMessage throughput: 43205 msg/s
- UdpMulticastServer
- UdpMulticastClient --clients 100
Server address: 239.255.0.1Server port: 3333Working clients: 100Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.035 sTotal data: 28.684 MiBTotal messages: 939408Data throughput: 2.877 MiB/sMessage latency: 10.682 mcsMessage throughput: 93606 msg/s
- UdsMulticastServer
- UdsMulticastClient --clients 1
Server Unix Domain Socket path: C:\Users\chronoxor\AppData\Local\Temp\multicast.sockWorking clients: 1Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.015 sTotal data: 204.127 MiBTotal messages: 6688763Data throughput: 20.390 MiB/sMessage latency: 1.497 mcsMessage throughput: 667869 msg/s
- UdsMulticastServer
- UdsMulticastClient --clients 100
Server Unix Domain Socket path: C:\Users\chronoxor\AppData\Local\Temp\multicast.sockWorking clients: 100Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.033 sTotal data: 124.463 MiBTotal messages: 4078051Data throughput: 12.413 MiB/sMessage latency: 2.460 mcsMessage throughput: 406451 msg/s
- WsMulticastServer
- WsMulticastClient --clients 1
Server address: 127.0.0.1Server port: 8080Working clients: 1Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.048 sTotal data: 183.108 MiBTotal messages: 6000000Data throughput: 18.228 MiB/sMessage latency: 1.674 mcsMessage throughput: 597121 msg/s
- WsMulticastServer
- WsMulticastClient --clients 100
Server address: 127.0.0.1Server port: 8080Working clients: 100Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.227 sTotal data: 125.957 MiBTotal messages: 4126627Data throughput: 12.320 MiB/sMessage latency: 2.478 mcsMessage throughput: 403466 msg/s
- WssMulticastServer
- WssMulticastClient --clients 1
Server address: 127.0.0.1Server port: 8443Working clients: 1Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.034 sTotal data: 184.159 MiBTotal messages: 6034421Data throughput: 18.359 MiB/sMessage latency: 1.662 mcsMessage throughput: 601338 msg/s
- WssMulticastServer
- WssMulticastClient --clients 100
Server address: 127.0.0.1Server port: 8443Working clients: 100Message size: 32Seconds to benchmarking: 10Errors: 0Total time: 10.171 sTotal data: 315.306 MiBTotal messages: 10331721Data throughput: 30.1022 MiB/sMessage latency: 984 nsMessage throughput: 1015763 msg/s
- HttpTraceServer
- HttpTraceClient --clients 1
Server address: 127.0.0.1Server port: 8080Working clients: 1Working messages: 1Seconds to benchmarking: 10Errors: 0Total time: 10.023 sTotal data: 10.987 MiBTotal messages: 108465Data throughput: 1.096 MiB/sMessage latency: 92.414 mcsMessage throughput: 10820 msg/s
- HttpTraceServer
- HttpTraceClient --clients 100
Server address: 127.0.0.1Server port: 8080Working clients: 100Working messages: 1Seconds to benchmarking: 10Errors: 0Total time: 10.085 sTotal data: 40.382 MiBTotal messages: 401472Data throughput: 4.003 MiB/sMessage latency: 25.120 mcsMessage throughput: 39807 msg/s
- HttpsTraceServer
- HttpsTraceClient --clients 1
Server address: 127.0.0.1Server port: 8443Working clients: 1Working messages: 1Seconds to benchmarking: 10Errors: 0Total time: 595.214 msTotal data: 627.842 KiBTotal messages: 6065Data throughput: 1.030 MiB/sMessage latency: 98.139 mcsMessage throughput: 10189 msg/s
- HttpsTraceServer
- HttpsTraceClient --clients 100
Server address: 127.0.0.1Server port: 8443Working clients: 100Working messages: 1Seconds to benchmarking: 10Errors: 0Total time: 3.548 sTotal data: 17.948 MiBTotal messages: 179111Data throughput: 5.052 MiB/sMessage latency: 19.813 mcsMessage throughput: 50471 msg/s
In order to create OpenSSL based server and client you should prepare a set ofSSL certificates.
Depending on your project, you may need to purchase a traditional SSLcertificate signed by a Certificate Authority. If you, for instance,want some else's web browser to talk to your WebSocket project, you'llneed a traditional SSL certificate.
The commands below entered in the order they are listed will generate aself-signed certificate for development or testing purposes.
- Create CA private key
openssl genrsa -passout pass:qwerty -out ca-secret.key 4096
- Remove passphrase
openssl rsa -passin pass:qwerty -in ca-secret.key -out ca.key
- Create CA self-signed certificate
openssl req -new -x509 -days 3650 -subj'/C=BY/ST=Belarus/L=Minsk/O=Example root CA/OU=Example CA unit/CN=example.com' -key ca.key -out ca.crt
- Convert CA self-signed certificate to PFX
openssl pkcs12 -export -passout pass:qwerty -inkey ca.key -in ca.crt -out ca.pfx
- Convert CA self-signed certificate to PEM
openssl pkcs12 -passin pass:qwerty -passout pass:qwerty -in ca.pfx -out ca.pem
- Create private key for the server
openssl genrsa -passout pass:qwerty -out server-secret.key 4096
- Remove passphrase
openssl rsa -passin pass:qwerty -in server-secret.key -out server.key
- Create CSR for the server
openssl req -new -subj'/C=BY/ST=Belarus/L=Minsk/O=Example server/OU=Example server unit/CN=server.example.com' -key server.key -out server.csr
- Create certificate for the server
openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
- Convert the server certificate to PFX
openssl pkcs12 -export -passout pass:qwerty -inkey server.key -in server.crt -out server.pfx
- Convert the server certificate to PEM
openssl pkcs12 -passin pass:qwerty -passout pass:qwerty -in server.pfx -out server.pem
- Create private key for the client
openssl genrsa -passout pass:qwerty -out client-secret.key 4096
- Remove passphrase
openssl rsa -passin pass:qwerty -in client-secret.key -out client.key
- Create CSR for the client
openssl req -new -subj'/C=BY/ST=Belarus/L=Minsk/O=Example client/OU=Example client unit/CN=client.example.com' -key client.key -out client.csr
- Create the client certificate
openssl x509 -req -days 3650 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt
- Convert the client certificate to PFX
openssl pkcs12 -export -passout pass:qwerty -inkey client.key -in client.crt -out client.pfx
- Convert the client certificate to PEM
openssl pkcs12 -passin pass:qwerty -passout pass:qwerty -in client.pfx -out client.pem
- Create DH parameters
openssl dhparam -out dh4096.pem 4096
About
Ultra fast and low latency asynchronous socket server & client C# .NET Core library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and 10K connections problem solution