项目作者: chronoxor

项目描述 :
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
高级语言: C#
项目地址: git://github.com/chronoxor/NetCoreServer.git
创建时间: 2019-01-16T22:41:53Z
项目社区:https://github.com/chronoxor/NetCoreServer

开源协议:MIT License

下载


NetCoreServer

Awesome .NET
License
Release
NuGet


Linux
MacOS
Windows (Visual Studio)

Ultra fast and low latency asynchronous socket server & client C# .NET Core
library with support TCP, SSL, UDP, Unix Domain Socket, HTTP, HTTPS, WebSocket protocols and 10K connections problem
solution.

Has integration with high-level message protocol based on Fast Binary Encoding

NetCoreServer documentation

NetCoreServer downloads

Contents

Features

Requirements

Optional:

How to build?

Setup repository

  1. git clone https://github.com/chronoxor/NetCoreServer.git
  2. cd NetCoreServer

Linux

  1. cd build
  2. ./unix.sh

MacOS

  1. cd build
  2. ./unix.sh

Windows (Visual Studio)

Open and build NetCoreServer.sln or run the build script:

  1. cd build
  2. vs.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

Examples

Example: TCP chat server

Here comes the example of the TCP chat server. It handles multiple TCP client
sessions and multicast received message from any session to all ones. Also it
is possible to send admin message directly from the server.

  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.Text;
  5. using NetCoreServer;
  6. namespace TcpChatServer
  7. {
  8. class ChatSession : TcpSession
  9. {
  10. public ChatSession(TcpServer server) : base(server) {}
  11. protected override void OnConnected()
  12. {
  13. Console.WriteLine($"Chat TCP session with Id {Id} connected!");
  14. // Send invite message
  15. string message = "Hello from TCP chat! Please send a message or '!' to disconnect the client!";
  16. SendAsync(message);
  17. }
  18. protected override void OnDisconnected()
  19. {
  20. Console.WriteLine($"Chat TCP session with Id {Id} disconnected!");
  21. }
  22. protected override void OnReceived(byte[] buffer, long offset, long size)
  23. {
  24. string message = Encoding.UTF8.GetString(buffer, (int)offset, (int)size);
  25. Console.WriteLine("Incoming: " + message);
  26. // Multicast message to all connected sessions
  27. Server.Multicast(message);
  28. // If the buffer starts with '!' the disconnect the current session
  29. if (message == "!")
  30. Disconnect();
  31. }
  32. protected override void OnError(SocketError error)
  33. {
  34. Console.WriteLine($"Chat TCP session caught an error with code {error}");
  35. }
  36. }
  37. class ChatServer : TcpServer
  38. {
  39. public ChatServer(IPAddress address, int port) : base(address, port) {}
  40. protected override TcpSession CreateSession() { return new ChatSession(this); }
  41. protected override void OnError(SocketError error)
  42. {
  43. Console.WriteLine($"Chat TCP server caught an error with code {error}");
  44. }
  45. }
  46. class Program
  47. {
  48. static void Main(string[] args)
  49. {
  50. // TCP server port
  51. int port = 1111;
  52. if (args.Length > 0)
  53. port = int.Parse(args[0]);
  54. Console.WriteLine($"TCP server port: {port}");
  55. Console.WriteLine();
  56. // Create a new TCP chat server
  57. var server = new ChatServer(IPAddress.Any, port);
  58. // Start the server
  59. Console.Write("Server starting...");
  60. server.Start();
  61. Console.WriteLine("Done!");
  62. Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");
  63. // Perform text input
  64. for (;;)
  65. {
  66. string line = Console.ReadLine();
  67. if (string.IsNullOrEmpty(line))
  68. break;
  69. // Restart the server
  70. if (line == "!")
  71. {
  72. Console.Write("Server restarting...");
  73. server.Restart();
  74. Console.WriteLine("Done!");
  75. continue;
  76. }
  77. // Multicast admin message to all sessions
  78. line = "(admin) " + line;
  79. server.Multicast(line);
  80. }
  81. // Stop the server
  82. Console.Write("Server stopping...");
  83. server.Stop();
  84. Console.WriteLine("Done!");
  85. }
  86. }
  87. }

Example: TCP chat client

Here comes the example of the TCP chat client. It connects to the TCP chat
server and allows to send message to it and receive new messages.

  1. using System;
  2. using System.Net.Sockets;
  3. using System.Text;
  4. using System.Threading;
  5. using TcpClient = NetCoreServer.TcpClient;
  6. namespace TcpChatClient
  7. {
  8. class ChatClient : TcpClient
  9. {
  10. public ChatClient(string address, int port) : base(address, port) {}
  11. public void DisconnectAndStop()
  12. {
  13. _stop = true;
  14. DisconnectAsync();
  15. while (IsConnected)
  16. Thread.Yield();
  17. }
  18. protected override void OnConnected()
  19. {
  20. Console.WriteLine($"Chat TCP client connected a new session with Id {Id}");
  21. }
  22. protected override void OnDisconnected()
  23. {
  24. Console.WriteLine($"Chat TCP client disconnected a session with Id {Id}");
  25. // Wait for a while...
  26. Thread.Sleep(1000);
  27. // Try to connect again
  28. if (!_stop)
  29. ConnectAsync();
  30. }
  31. protected override void OnReceived(byte[] buffer, long offset, long size)
  32. {
  33. Console.WriteLine(Encoding.UTF8.GetString(buffer, (int)offset, (int)size));
  34. }
  35. protected override void OnError(SocketError error)
  36. {
  37. Console.WriteLine($"Chat TCP client caught an error with code {error}");
  38. }
  39. private bool _stop;
  40. }
  41. class Program
  42. {
  43. static void Main(string[] args)
  44. {
  45. // TCP server address
  46. string address = "127.0.0.1";
  47. if (args.Length > 0)
  48. address = args[0];
  49. // TCP server port
  50. int port = 1111;
  51. if (args.Length > 1)
  52. port = int.Parse(args[1]);
  53. Console.WriteLine($"TCP server address: {address}");
  54. Console.WriteLine($"TCP server port: {port}");
  55. Console.WriteLine();
  56. // Create a new TCP chat client
  57. var client = new ChatClient(address, port);
  58. // Connect the client
  59. Console.Write("Client connecting...");
  60. client.ConnectAsync();
  61. Console.WriteLine("Done!");
  62. Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");
  63. // Perform text input
  64. for (;;)
  65. {
  66. string line = Console.ReadLine();
  67. if (string.IsNullOrEmpty(line))
  68. break;
  69. // Disconnect the client
  70. if (line == "!")
  71. {
  72. Console.Write("Client disconnecting...");
  73. client.DisconnectAsync();
  74. Console.WriteLine("Done!");
  75. continue;
  76. }
  77. // Send the entered text to the chat server
  78. client.SendAsync(line);
  79. }
  80. // Disconnect the client
  81. Console.Write("Client disconnecting...");
  82. client.DisconnectAndStop();
  83. Console.WriteLine("Done!");
  84. }
  85. }
  86. }

Example: SSL chat server

Here comes the example of the SSL chat server. It handles multiple SSL client
sessions and multicast received message from any session to all ones. Also it
is possible to send admin message directly from the server.

This example is very similar to the TCP one except the code that prepares SSL
context and handshake handler.

  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.Security.Authentication;
  5. using System.Security.Cryptography.X509Certificates;
  6. using System.Text;
  7. using NetCoreServer;
  8. namespace SslChatServer
  9. {
  10. class ChatSession : SslSession
  11. {
  12. public ChatSession(SslServer server) : base(server) {}
  13. protected override void OnConnected()
  14. {
  15. Console.WriteLine($"Chat SSL session with Id {Id} connected!");
  16. }
  17. protected override void OnHandshaked()
  18. {
  19. Console.WriteLine($"Chat SSL session with Id {Id} handshaked!");
  20. // Send invite message
  21. string message = "Hello from SSL chat! Please send a message or '!' to disconnect the client!";
  22. Send(message);
  23. }
  24. protected override void OnDisconnected()
  25. {
  26. Console.WriteLine($"Chat SSL session with Id {Id} disconnected!");
  27. }
  28. protected override void OnReceived(byte[] buffer, long offset, long size)
  29. {
  30. string message = Encoding.UTF8.GetString(buffer, (int)offset, (int)size);
  31. Console.WriteLine("Incoming: " + message);
  32. // Multicast message to all connected sessions
  33. Server.Multicast(message);
  34. // If the buffer starts with '!' the disconnect the current session
  35. if (message == "!")
  36. Disconnect();
  37. }
  38. protected override void OnError(SocketError error)
  39. {
  40. Console.WriteLine($"Chat SSL session caught an error with code {error}");
  41. }
  42. }
  43. class ChatServer : SslServer
  44. {
  45. public ChatServer(SslContext context, IPAddress address, int port) : base(context, address, port) {}
  46. protected override SslSession CreateSession() { return new ChatSession(this); }
  47. protected override void OnError(SocketError error)
  48. {
  49. Console.WriteLine($"Chat SSL server caught an error with code {error}");
  50. }
  51. }
  52. class Program
  53. {
  54. static void Main(string[] args)
  55. {
  56. // SSL server port
  57. int port = 2222;
  58. if (args.Length > 0)
  59. port = int.Parse(args[0]);
  60. Console.WriteLine($"SSL server port: {port}");
  61. Console.WriteLine();
  62. // Create and prepare a new SSL server context
  63. var context = new SslContext(SslProtocols.Tls12, new X509Certificate2("server.pfx", "qwerty"));
  64. // Create a new SSL chat server
  65. var server = new ChatServer(context, IPAddress.Any, port);
  66. // Start the server
  67. Console.Write("Server starting...");
  68. server.Start();
  69. Console.WriteLine("Done!");
  70. Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");
  71. // Perform text input
  72. for (;;)
  73. {
  74. string line = Console.ReadLine();
  75. if (string.IsNullOrEmpty(line))
  76. break;
  77. // Restart the server
  78. if (line == "!")
  79. {
  80. Console.Write("Server restarting...");
  81. server.Restart();
  82. Console.WriteLine("Done!");
  83. continue;
  84. }
  85. // Multicast admin message to all sessions
  86. line = "(admin) " + line;
  87. server.Multicast(line);
  88. }
  89. // Stop the server
  90. Console.Write("Server stopping...");
  91. server.Stop();
  92. Console.WriteLine("Done!");
  93. }
  94. }
  95. }

Example: SSL chat client

Here comes the example of the SSL chat client. It connects to the SSL chat
server 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 SSL
context and handshake handler.

  1. using System;
  2. using System.Net.Sockets;
  3. using System.Security.Authentication;
  4. using System.Security.Cryptography.X509Certificates;
  5. using System.Text;
  6. using System.Threading;
  7. using NetCoreServer;
  8. namespace SslChatClient
  9. {
  10. class ChatClient : SslClient
  11. {
  12. public ChatClient(SslContext context, string address, int port) : base(context, address, port) {}
  13. public void DisconnectAndStop()
  14. {
  15. _stop = true;
  16. DisconnectAsync();
  17. while (IsConnected)
  18. Thread.Yield();
  19. }
  20. protected override void OnConnected()
  21. {
  22. Console.WriteLine($"Chat SSL client connected a new session with Id {Id}");
  23. }
  24. protected override void OnHandshaked()
  25. {
  26. Console.WriteLine($"Chat SSL client handshaked a new session with Id {Id}");
  27. }
  28. protected override void OnDisconnected()
  29. {
  30. Console.WriteLine($"Chat SSL client disconnected a session with Id {Id}");
  31. // Wait for a while...
  32. Thread.Sleep(1000);
  33. // Try to connect again
  34. if (!_stop)
  35. ConnectAsync();
  36. }
  37. protected override void OnReceived(byte[] buffer, long offset, long size)
  38. {
  39. Console.WriteLine(Encoding.UTF8.GetString(buffer, (int)offset, (int)size));
  40. }
  41. protected override void OnError(SocketError error)
  42. {
  43. Console.WriteLine($"Chat SSL client caught an error with code {error}");
  44. }
  45. private bool _stop;
  46. }
  47. class Program
  48. {
  49. static void Main(string[] args)
  50. {
  51. // SSL server address
  52. string address = "127.0.0.1";
  53. if (args.Length > 0)
  54. address = args[0];
  55. // SSL server port
  56. int port = 2222;
  57. if (args.Length > 1)
  58. port = int.Parse(args[1]);
  59. Console.WriteLine($"SSL server address: {address}");
  60. Console.WriteLine($"SSL server port: {port}");
  61. Console.WriteLine();
  62. // Create and prepare a new SSL client context
  63. var context = new SslContext(SslProtocols.Tls12, new X509Certificate2("client.pfx", "qwerty"), (sender, certificate, chain, sslPolicyErrors) => true);
  64. // Create a new SSL chat client
  65. var client = new ChatClient(context, address, port);
  66. // Connect the client
  67. Console.Write("Client connecting...");
  68. client.ConnectAsync();
  69. Console.WriteLine("Done!");
  70. Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");
  71. // Perform text input
  72. for (;;)
  73. {
  74. string line = Console.ReadLine();
  75. if (string.IsNullOrEmpty(line))
  76. break;
  77. // Disconnect the client
  78. if (line == "!")
  79. {
  80. Console.Write("Client disconnecting...");
  81. client.DisconnectAsync();
  82. Console.WriteLine("Done!");
  83. continue;
  84. }
  85. // Send the entered text to the chat server
  86. client.SendAsync(line);
  87. }
  88. // Disconnect the client
  89. Console.Write("Client disconnecting...");
  90. client.DisconnectAndStop();
  91. Console.WriteLine("Done!");
  92. }
  93. }
  94. }

Example: UDP echo server

Here comes the example of the UDP echo server. It receives a datagram mesage
from any UDP client and resend it back without any changes.

  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.Text;
  5. using NetCoreServer;
  6. namespace UdpEchoServer
  7. {
  8. class EchoServer : UdpServer
  9. {
  10. public EchoServer(IPAddress address, int port) : base(address, port) {}
  11. protected override void OnStarted()
  12. {
  13. // Start receive datagrams
  14. ReceiveAsync();
  15. }
  16. protected override void OnReceived(EndPoint endpoint, byte[] buffer, long offset, long size)
  17. {
  18. Console.WriteLine("Incoming: " + Encoding.UTF8.GetString(buffer, (int)offset, (int)size));
  19. // Echo the message back to the sender
  20. SendAsync(endpoint, buffer, 0, size);
  21. }
  22. protected override void OnSent(EndPoint endpoint, long sent)
  23. {
  24. // Continue receive datagrams
  25. ReceiveAsync();
  26. }
  27. protected override void OnError(SocketError error)
  28. {
  29. Console.WriteLine($"Echo UDP server caught an error with code {error}");
  30. }
  31. }
  32. class Program
  33. {
  34. static void Main(string[] args)
  35. {
  36. // UDP server port
  37. int port = 3333;
  38. if (args.Length > 0)
  39. port = int.Parse(args[0]);
  40. Console.WriteLine($"UDP server port: {port}");
  41. Console.WriteLine();
  42. // Create a new UDP echo server
  43. var server = new EchoServer(IPAddress.Any, port);
  44. // Start the server
  45. Console.Write("Server starting...");
  46. server.Start();
  47. Console.WriteLine("Done!");
  48. Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");
  49. // Perform text input
  50. for (;;)
  51. {
  52. string line = Console.ReadLine();
  53. if (string.IsNullOrEmpty(line))
  54. break;
  55. // Restart the server
  56. if (line == "!")
  57. {
  58. Console.Write("Server restarting...");
  59. server.Restart();
  60. Console.WriteLine("Done!");
  61. }
  62. }
  63. // Stop the server
  64. Console.Write("Server stopping...");
  65. server.Stop();
  66. Console.WriteLine("Done!");
  67. }
  68. }
  69. }

Example: UDP echo client

Here comes the example of the UDP echo client. It sends user datagram message
to UDP server and listen for response.

  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.Text;
  5. using System.Threading;
  6. using UdpClient = NetCoreServer.UdpClient;
  7. namespace UdpEchoClient
  8. {
  9. class EchoClient : UdpClient
  10. {
  11. public EchoClient(string address, int port) : base(address, port) {}
  12. public void DisconnectAndStop()
  13. {
  14. _stop = true;
  15. Disconnect();
  16. while (IsConnected)
  17. Thread.Yield();
  18. }
  19. protected override void OnConnected()
  20. {
  21. Console.WriteLine($"Echo UDP client connected a new session with Id {Id}");
  22. // Start receive datagrams
  23. ReceiveAsync();
  24. }
  25. protected override void OnDisconnected()
  26. {
  27. Console.WriteLine($"Echo UDP client disconnected a session with Id {Id}");
  28. // Wait for a while...
  29. Thread.Sleep(1000);
  30. // Try to connect again
  31. if (!_stop)
  32. Connect();
  33. }
  34. protected override void OnReceived(EndPoint endpoint, byte[] buffer, long offset, long size)
  35. {
  36. Console.WriteLine("Incoming: " + Encoding.UTF8.GetString(buffer, (int)offset, (int)size));
  37. // Continue receive datagrams
  38. ReceiveAsync();
  39. }
  40. protected override void OnError(SocketError error)
  41. {
  42. Console.WriteLine($"Echo UDP client caught an error with code {error}");
  43. }
  44. private bool _stop;
  45. }
  46. class Program
  47. {
  48. static void Main(string[] args)
  49. {
  50. // UDP server address
  51. string address = "127.0.0.1";
  52. if (args.Length > 0)
  53. address = args[0];
  54. // UDP server port
  55. int port = 3333;
  56. if (args.Length > 1)
  57. port = int.Parse(args[1]);
  58. Console.WriteLine($"UDP server address: {address}");
  59. Console.WriteLine($"UDP server port: {port}");
  60. Console.WriteLine();
  61. // Create a new TCP chat client
  62. var client = new EchoClient(address, port);
  63. // Connect the client
  64. Console.Write("Client connecting...");
  65. client.Connect();
  66. Console.WriteLine("Done!");
  67. Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");
  68. // Perform text input
  69. for (;;)
  70. {
  71. string line = Console.ReadLine();
  72. if (string.IsNullOrEmpty(line))
  73. break;
  74. // Disconnect the client
  75. if (line == "!")
  76. {
  77. Console.Write("Client disconnecting...");
  78. client.Disconnect();
  79. Console.WriteLine("Done!");
  80. continue;
  81. }
  82. // Send the entered text to the chat server
  83. client.Send(line);
  84. }
  85. // Disconnect the client
  86. Console.Write("Client disconnecting...");
  87. client.DisconnectAndStop();
  88. Console.WriteLine("Done!");
  89. }
  90. }
  91. }

Example: UDP multicast server

Here comes the example of the UDP multicast server. It use multicast IP address
to multicast datagram messages to all client that joined corresponding UDP
multicast group.

  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using NetCoreServer;
  5. namespace UdpMulticastServer
  6. {
  7. class MulticastServer : UdpServer
  8. {
  9. public MulticastServer(IPAddress address, int port) : base(address, port) {}
  10. protected override void OnError(SocketError error)
  11. {
  12. Console.WriteLine($"Multicast UDP server caught an error with code {error}");
  13. }
  14. }
  15. class Program
  16. {
  17. static void Main(string[] args)
  18. {
  19. // UDP multicast address
  20. string multicastAddress = "239.255.0.1";
  21. if (args.Length > 0)
  22. multicastAddress = args[0];
  23. // UDP multicast port
  24. int multicastPort = 3334;
  25. if (args.Length > 1)
  26. multicastPort = int.Parse(args[1]);
  27. Console.WriteLine($"UDP multicast address: {multicastAddress}");
  28. Console.WriteLine($"UDP multicast port: {multicastPort}");
  29. Console.WriteLine();
  30. // Create a new UDP multicast server
  31. var server = new MulticastServer(IPAddress.Any, 0);
  32. // Start the multicast server
  33. Console.Write("Server starting...");
  34. server.Start(multicastAddress, multicastPort);
  35. Console.WriteLine("Done!");
  36. Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");
  37. // Perform text input
  38. for (;;)
  39. {
  40. string line = Console.ReadLine();
  41. if (string.IsNullOrEmpty(line))
  42. break;
  43. // Restart the server
  44. if (line == "!")
  45. {
  46. Console.Write("Server restarting...");
  47. server.Restart();
  48. Console.WriteLine("Done!");
  49. continue;
  50. }
  51. // Multicast admin message to all sessions
  52. line = "(admin) " + line;
  53. server.Multicast(line);
  54. }
  55. // Stop the server
  56. Console.Write("Server stopping...");
  57. server.Stop();
  58. Console.WriteLine("Done!");
  59. }
  60. }
  61. }

Example: UDP multicast client

Here comes the example of the UDP multicast client. It use multicast IP address
and joins UDP multicast group in order to receive multicasted datagram messages
from UDP server.

  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.Text;
  5. using System.Threading;
  6. using UdpClient = NetCoreServer.UdpClient;
  7. namespace UdpMulticastClient
  8. {
  9. class MulticastClient : UdpClient
  10. {
  11. public string Multicast;
  12. public MulticastClient(string address, int port) : base(address, port) {}
  13. public void DisconnectAndStop()
  14. {
  15. _stop = true;
  16. Disconnect();
  17. while (IsConnected)
  18. Thread.Yield();
  19. }
  20. protected override void OnConnected()
  21. {
  22. Console.WriteLine($"Multicast UDP client connected a new session with Id {Id}");
  23. // Join UDP multicast group
  24. JoinMulticastGroup(Multicast);
  25. // Start receive datagrams
  26. ReceiveAsync();
  27. }
  28. protected override void OnDisconnected()
  29. {
  30. Console.WriteLine($"Multicast UDP client disconnected a session with Id {Id}");
  31. // Wait for a while...
  32. Thread.Sleep(1000);
  33. // Try to connect again
  34. if (!_stop)
  35. Connect();
  36. }
  37. protected override void OnReceived(EndPoint endpoint, byte[] buffer, long offset, long size)
  38. {
  39. Console.WriteLine("Incoming: " + Encoding.UTF8.GetString(buffer, (int)offset, (int)size));
  40. // Continue receive datagrams
  41. ReceiveAsync();
  42. }
  43. protected override void OnError(SocketError error)
  44. {
  45. Console.WriteLine($"Multicast UDP client caught an error with code {error}");
  46. }
  47. private bool _stop;
  48. }
  49. class Program
  50. {
  51. static void Main(string[] args)
  52. {
  53. // UDP listen address
  54. string listenAddress = "0.0.0.0";
  55. if (args.Length > 0)
  56. listenAddress = args[0];
  57. // UDP multicast address
  58. string multicastAddress = "239.255.0.1";
  59. if (args.Length > 1)
  60. multicastAddress = args[1];
  61. // UDP multicast port
  62. int multicastPort = 3334;
  63. if (args.Length > 2)
  64. multicastPort = int.Parse(args[2]);
  65. Console.WriteLine($"UDP listen address: {listenAddress}");
  66. Console.WriteLine($"UDP multicast address: {multicastAddress}");
  67. Console.WriteLine($"UDP multicast port: {multicastPort}");
  68. Console.WriteLine();
  69. // Create a new TCP chat client
  70. var client = new MulticastClient(listenAddress, multicastPort);
  71. client.SetupMulticast(true);
  72. client.Multicast = multicastAddress;
  73. // Connect the client
  74. Console.Write("Client connecting...");
  75. client.Connect();
  76. Console.WriteLine("Done!");
  77. Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");
  78. // Perform text input
  79. for (;;)
  80. {
  81. string line = Console.ReadLine();
  82. if (string.IsNullOrEmpty(line))
  83. break;
  84. // Disconnect the client
  85. if (line == "!")
  86. {
  87. Console.Write("Client disconnecting...");
  88. client.Disconnect();
  89. Console.WriteLine("Done!");
  90. continue;
  91. }
  92. }
  93. // Disconnect the client
  94. Console.Write("Client disconnecting...");
  95. client.DisconnectAndStop();
  96. Console.WriteLine("Done!");
  97. }
  98. }
  99. }

Example: Unix Domain Socket chat server

Here comes the example of the Unix Domain Socket chat server. It handles
multiple Unix Domain Socket client sessions and multicast received message from
any session to all ones. Also it is possible to send admin message directly
from the server.

  1. using System;
  2. using System.IO;
  3. using System.Net.Sockets;
  4. using System.Text;
  5. using NetCoreServer;
  6. namespace UdsChatServer
  7. {
  8. class ChatSession : UdsSession
  9. {
  10. public ChatSession(UdsServer server) : base(server) {}
  11. protected override void OnConnected()
  12. {
  13. Console.WriteLine($"Chat Unix Domain Socket session with Id {Id} connected!");
  14. // Send invite message
  15. string message = "Hello from Unix Domain Socket chat! Please send a message or '!' to disconnect the client!";
  16. SendAsync(message);
  17. }
  18. protected override void OnDisconnected()
  19. {
  20. Console.WriteLine($"Chat Unix Domain Socket session with Id {Id} disconnected!");
  21. }
  22. protected override void OnReceived(byte[] buffer, long offset, long size)
  23. {
  24. string message = Encoding.UTF8.GetString(buffer, (int)offset, (int)size);
  25. Console.WriteLine("Incoming: " + message);
  26. // Multicast message to all connected sessions
  27. Server.Multicast(message);
  28. // If the buffer starts with '!' the disconnect the current session
  29. if (message == "!")
  30. Disconnect();
  31. }
  32. protected override void OnError(SocketError error)
  33. {
  34. Console.WriteLine($"Chat Unix Domain Socket session caught an error with code {error}");
  35. }
  36. }
  37. class ChatServer : UdsServer
  38. {
  39. public ChatServer(string path) : base(path) {}
  40. protected override UdsSession CreateSession() { return new ChatSession(this); }
  41. protected override void OnError(SocketError error)
  42. {
  43. Console.WriteLine($"Chat Unix Domain Socket server caught an error with code {error}");
  44. }
  45. }
  46. class Program
  47. {
  48. static void Main(string[] args)
  49. {
  50. // Unix Domain Socket path
  51. string path = Path.Combine(Path.GetTempPath(), "chat.sock");
  52. if (args.Length > 0)
  53. path = args[0];
  54. Console.WriteLine($"Unix Domain Socket server path: {path}");
  55. Console.WriteLine();
  56. // Create a new Unix Domain Socket chat server
  57. var server = new ChatServer(path);
  58. // Start the server
  59. Console.Write("Server starting...");
  60. server.Start();
  61. Console.WriteLine("Done!");
  62. Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");
  63. // Perform text input
  64. for (;;)
  65. {
  66. string line = Console.ReadLine();
  67. if (string.IsNullOrEmpty(line))
  68. break;
  69. // Restart the server
  70. if (line == "!")
  71. {
  72. Console.Write("Server restarting...");
  73. server.Restart();
  74. Console.WriteLine("Done!");
  75. continue;
  76. }
  77. // Multicast admin message to all sessions
  78. line = "(admin) " + line;
  79. server.Multicast(line);
  80. }
  81. // Stop the server
  82. Console.Write("Server stopping...");
  83. server.Stop();
  84. Console.WriteLine("Done!");
  85. }
  86. }
  87. }

Example: Unix Domain Socket chat client

Here comes the example of the Unix Domain Socket chat client. It connects to
the Unix Domain Socket chat server and allows to send message to it and receive
new messages.

  1. using System;
  2. using System.IO;
  3. using System.Net.Sockets;
  4. using System.Text;
  5. using System.Threading;
  6. using UdsClient = NetCoreServer.UdsClient;
  7. namespace UdsChatClient
  8. {
  9. class ChatClient : UdsClient
  10. {
  11. public ChatClient(string path) : base(path) {}
  12. public void DisconnectAndStop()
  13. {
  14. _stop = true;
  15. DisconnectAsync();
  16. while (IsConnected)
  17. Thread.Yield();
  18. }
  19. protected override void OnConnected()
  20. {
  21. Console.WriteLine($"Chat Unix Domain Socket client connected a new session with Id {Id}");
  22. }
  23. protected override void OnDisconnected()
  24. {
  25. Console.WriteLine($"Chat Unix Domain Socket client disconnected a session with Id {Id}");
  26. // Wait for a while...
  27. Thread.Sleep(1000);
  28. // Try to connect again
  29. if (!_stop)
  30. ConnectAsync();
  31. }
  32. protected override void OnReceived(byte[] buffer, long offset, long size)
  33. {
  34. Console.WriteLine(Encoding.UTF8.GetString(buffer, (int)offset, (int)size));
  35. }
  36. protected override void OnError(SocketError error)
  37. {
  38. Console.WriteLine($"Chat Unix Domain Socket client caught an error with code {error}");
  39. }
  40. private bool _stop;
  41. }
  42. class Program
  43. {
  44. static void Main(string[] args)
  45. {
  46. // Unix Domain Socket path
  47. string path = Path.Combine(Path.GetTempPath(), "chat.sock");
  48. if (args.Length > 0)
  49. path = args[0];
  50. Console.WriteLine($"Unix Domain Socket server path: {path}");
  51. Console.WriteLine();
  52. // Create a new Unix Domain Socket chat client
  53. var client = new ChatClient(path);
  54. // Connect the client
  55. Console.Write("Client connecting...");
  56. client.ConnectAsync();
  57. Console.WriteLine("Done!");
  58. Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");
  59. // Perform text input
  60. for (;;)
  61. {
  62. string line = Console.ReadLine();
  63. if (string.IsNullOrEmpty(line))
  64. break;
  65. // Disconnect the client
  66. if (line == "!")
  67. {
  68. Console.Write("Client disconnecting...");
  69. client.DisconnectAsync();
  70. Console.WriteLine("Done!");
  71. continue;
  72. }
  73. // Send the entered text to the chat server
  74. client.SendAsync(line);
  75. }
  76. // Disconnect the client
  77. Console.Write("Client disconnecting...");
  78. client.DisconnectAndStop();
  79. Console.WriteLine("Done!");
  80. }
  81. }
  82. }

Example: Simple protocol

Simple protocol is defined in simple.fbe file:

  1. /*
  2. Simple Fast Binary Encoding protocol for CppServer
  3. https://github.com/chronoxor/FastBinaryEncoding
  4. Generate protocol command: fbec --csharp --proto --input=simple.fbe --output=.
  5. */
  6. // Domain declaration
  7. domain com.chronoxor
  8. // Package declaration
  9. package simple
  10. // Protocol version
  11. version 1.0
  12. // Simple request message
  13. [request]
  14. [response(SimpleResponse)]
  15. [reject(SimpleReject)]
  16. message SimpleRequest
  17. {
  18. // Request Id
  19. uuid [id] = uuid1;
  20. // Request message
  21. string Message;
  22. }
  23. // Simple response
  24. message SimpleResponse
  25. {
  26. // Response Id
  27. uuid [id] = uuid1;
  28. // Calculated message length
  29. uint32 Length;
  30. // Calculated message hash
  31. uint32 Hash;
  32. }
  33. // Simple reject
  34. message SimpleReject
  35. {
  36. // Reject Id
  37. uuid [id] = uuid1;
  38. // Error message
  39. string Error;
  40. }
  41. // Simple notification
  42. message SimpleNotify
  43. {
  44. // Server notification
  45. string Notification;
  46. }
  47. // Disconnect request message
  48. [request]
  49. message DisconnectRequest
  50. {
  51. // Request Id
  52. uuid [id] = uuid1;
  53. }

Example: Simple protocol server

Here comes the example of the simple protocol server. It process client
requests, answer with corresponding responses and send server notifications
back to clients.

  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using NetCoreServer;
  5. using com.chronoxor.simple;
  6. using com.chronoxor.simple.FBE;
  7. namespace ProtoServer
  8. {
  9. public class SimpleProtoSessionSender : Sender, ISenderListener
  10. {
  11. public SimpleProtoSession Session { get; }
  12. public SimpleProtoSessionSender(SimpleProtoSession session) { Session = session; }
  13. public long OnSend(byte[] buffer, long offset, long size)
  14. {
  15. return Session.SendAsync(buffer, offset, size) ? size : 0;
  16. }
  17. }
  18. public class SimpleProtoSessionReceiver : Receiver, IReceiverListener
  19. {
  20. public SimpleProtoSession Session { get; }
  21. public SimpleProtoSessionReceiver(SimpleProtoSession session) { Session = session; }
  22. public void OnReceive(DisconnectRequest request) { Session.OnReceive(request); }
  23. public void OnReceive(SimpleRequest request) { Session.OnReceive(request); }
  24. }
  25. public class SimpleProtoSession : TcpSession
  26. {
  27. public SimpleProtoSessionSender Sender { get; }
  28. public SimpleProtoSessionReceiver Receiver { get; }
  29. public SimpleProtoSession(TcpServer server) : base(server)
  30. {
  31. Sender = new SimpleProtoSessionSender(this);
  32. Receiver = new SimpleProtoSessionReceiver(this);
  33. }
  34. protected override void OnConnected()
  35. {
  36. Console.WriteLine($"TCP protocol session with Id '{Id}' connected to remote address '{(Socket.RemoteEndPoint as IPEndPoint)?.Address}' and port {(Socket.RemoteEndPoint as IPEndPoint)?.Port}");
  37. // Send invite notification
  38. SimpleNotify notify = SimpleNotify.Default;
  39. notify.Notification = "Hello from Simple protocol server! Please send a message or '!' to disconnect the client!";
  40. Sender.Send(notify);
  41. }
  42. protected override void OnDisconnected()
  43. {
  44. Console.WriteLine($"TCP protocol session with Id '{Id}' disconnected");
  45. }
  46. protected override void OnReceived(byte[] buffer, long offset, long size)
  47. {
  48. Receiver.Receive(buffer, offset, size);
  49. }
  50. protected override void OnError(SocketError error)
  51. {
  52. Console.WriteLine($"TCP protocol session with Id '{Id}' caught a socket error: {error}");
  53. }
  54. // Protocol handlers
  55. public void OnReceive(DisconnectRequest request) { Disconnect(); }
  56. public void OnReceive(SimpleRequest request)
  57. {
  58. Console.WriteLine($"Received: {request}");
  59. // Validate request
  60. if (string.IsNullOrEmpty(request.Message))
  61. {
  62. // Send reject
  63. SimpleReject reject = SimpleReject.Default;
  64. reject.id = request.id;
  65. reject.Error = "Request message is empty!";
  66. Sender.Send(reject);
  67. return;
  68. }
  69. // Send response
  70. SimpleResponse response = SimpleResponse.Default;
  71. response.id = request.id;
  72. response.Hash = (uint)request.Message.GetHashCode();
  73. response.Length = (uint)request.Message.Length;
  74. Sender.Send(response);
  75. }
  76. }
  77. public class SimpleProtoSender : Sender, ISenderListener
  78. {
  79. public SimpleProtoServer Server { get; }
  80. public SimpleProtoSender(SimpleProtoServer server) { Server = server; }
  81. public long OnSend(byte[] buffer, long offset, long size)
  82. {
  83. Server.Multicast(buffer, offset, size);
  84. return size;
  85. }
  86. }
  87. public class SimpleProtoServer : TcpServer
  88. {
  89. public SimpleProtoSender Sender { get; }
  90. public SimpleProtoServer(IPAddress address, int port) : base(address, port)
  91. {
  92. Sender = new SimpleProtoSender(this);
  93. }
  94. protected override TcpSession CreateSession() { return new SimpleProtoSession(this); }
  95. protected override void OnStarted()
  96. {
  97. Console.WriteLine($"Simple protocol server with Id '{Id}' started!");
  98. }
  99. protected override void OnStopped()
  100. {
  101. Console.WriteLine($"Simple protocol server with Id '{Id}' stopped!");
  102. }
  103. protected override void OnError(SocketError error)
  104. {
  105. Console.WriteLine($"Simple protocol server with Id '{Id}' caught an error: {error}");
  106. }
  107. }
  108. class Program
  109. {
  110. static void Main(string[] args)
  111. {
  112. // Simple protocol server port
  113. int port = 4444;
  114. if (args.Length > 0)
  115. port = int.Parse(args[0]);
  116. Console.WriteLine($"Simple protocol server port: {port}");
  117. Console.WriteLine();
  118. // Create a new simple protocol server
  119. var server = new SimpleProtoServer(IPAddress.Any, port);
  120. // Start the server
  121. Console.Write("Server starting...");
  122. server.Start();
  123. Console.WriteLine("Done!");
  124. Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");
  125. // Perform text input
  126. for (;;)
  127. {
  128. string line = Console.ReadLine();
  129. if (string.IsNullOrEmpty(line))
  130. break;
  131. // Restart the server
  132. if (line == "!")
  133. {
  134. Console.Write("Server restarting...");
  135. server.Restart();
  136. Console.WriteLine("Done!");
  137. continue;
  138. }
  139. // Multicast admin notification to all sessions
  140. SimpleNotify notify = SimpleNotify.Default;
  141. notify.Notification = "(admin) " + line;
  142. server.Sender.Send(notify);
  143. }
  144. // Stop the server
  145. Console.Write("Server stopping...");
  146. server.Stop();
  147. Console.WriteLine("Done!");
  148. }
  149. }
  150. }

Example: Simple protocol client

Here comes the example of the simple protocol client. It connects to the
simple protocol server and allows to send requests to it and receive
corresponding responses.

  1. using System;
  2. using System.Net.Sockets;
  3. using System.Threading;
  4. using TcpClient = NetCoreServer.TcpClient;
  5. using com.chronoxor.simple;
  6. using com.chronoxor.simple.FBE;
  7. namespace ProtoClient
  8. {
  9. public class TcpProtoClient : TcpClient
  10. {
  11. public TcpProtoClient(string address, int port) : base(address, port) {}
  12. public bool ConnectAndStart()
  13. {
  14. Console.WriteLine($"TCP protocol client starting a new session with Id '{Id}'...");
  15. StartReconnectTimer();
  16. return ConnectAsync();
  17. }
  18. public bool DisconnectAndStop()
  19. {
  20. Console.WriteLine($"TCP protocol client stopping the session with Id '{Id}'...");
  21. StopReconnectTimer();
  22. DisconnectAsync();
  23. return true;
  24. }
  25. public override bool Reconnect()
  26. {
  27. return ReconnectAsync();
  28. }
  29. private Timer _reconnectTimer;
  30. public void StartReconnectTimer()
  31. {
  32. // Start the reconnect timer
  33. _reconnectTimer = new Timer(state =>
  34. {
  35. Console.WriteLine($"TCP reconnect timer connecting the client session with Id '{Id}'...");
  36. ConnectAsync();
  37. }, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
  38. }
  39. public void StopReconnectTimer()
  40. {
  41. // Stop the reconnect timer
  42. _reconnectTimer?.Dispose();
  43. _reconnectTimer = null;
  44. }
  45. public delegate void ConnectedHandler();
  46. public event ConnectedHandler Connected = () => {};
  47. protected override void OnConnected()
  48. {
  49. Console.WriteLine($"TCP protocol client connected a new session with Id '{Id}' to remote address '{Address}' and port {Port}");
  50. Connected?.Invoke();
  51. }
  52. public delegate void DisconnectedHandler();
  53. public event DisconnectedHandler Disconnected = () => {};
  54. protected override void OnDisconnected()
  55. {
  56. Console.WriteLine($"TCP protocol client disconnected the session with Id '{Id}'");
  57. // Setup and asynchronously wait for the reconnect timer
  58. _reconnectTimer?.Change(TimeSpan.FromSeconds(1), Timeout.InfiniteTimeSpan);
  59. Disconnected?.Invoke();
  60. }
  61. public delegate void ReceivedHandler(byte[] buffer, long offset, long size);
  62. public event ReceivedHandler Received = (buffer, offset, size) => {};
  63. protected override void OnReceived(byte[] buffer, long offset, long size)
  64. {
  65. Received?.Invoke(buffer, offset, size);
  66. }
  67. protected override void OnError(SocketError error)
  68. {
  69. Console.WriteLine($"TCP protocol client caught a socket error: {error}");
  70. }
  71. #region IDisposable implementation
  72. // Disposed flag.
  73. private bool _disposed;
  74. protected override void Dispose(bool disposingManagedResources)
  75. {
  76. if (!_disposed)
  77. {
  78. if (disposingManagedResources)
  79. {
  80. // Dispose managed resources here...
  81. StopReconnectTimer();
  82. }
  83. // Dispose unmanaged resources here...
  84. // Set large fields to null here...
  85. // Mark as disposed.
  86. _disposed = true;
  87. }
  88. // Call Dispose in the base class.
  89. base.Dispose(disposingManagedResources);
  90. }
  91. // The derived class does not have a Finalize method
  92. // or a Dispose method without parameters because it inherits
  93. // them from the base class.
  94. #endregion
  95. }
  96. public class SimpleProtoClient : Client, ISenderListener, IReceiverListener, IDisposable
  97. {
  98. private readonly TcpProtoClient _tcpProtoClient;
  99. public Guid Id => _tcpProtoClient.Id;
  100. public bool IsConnected => _tcpProtoClient.IsConnected;
  101. public SimpleProtoClient(string address, int port)
  102. {
  103. _tcpProtoClient = new TcpProtoClient(address, port);
  104. _tcpProtoClient.Connected += OnConnected;
  105. _tcpProtoClient.Disconnected += OnDisconnected;
  106. _tcpProtoClient.Received += OnReceived;
  107. ReceivedResponse_DisconnectRequest += HandleDisconnectRequest;
  108. ReceivedResponse_SimpleResponse += HandleSimpleResponse;
  109. ReceivedResponse_SimpleReject += HandleSimpleReject;
  110. ReceivedResponse_SimpleNotify += HandleSimpleNotify;
  111. }
  112. private void DisposeClient()
  113. {
  114. _tcpProtoClient.Connected -= OnConnected;
  115. _tcpProtoClient.Connected -= OnDisconnected;
  116. _tcpProtoClient.Received -= OnReceived;
  117. ReceivedResponse_DisconnectRequest -= HandleDisconnectRequest;
  118. ReceivedResponse_SimpleResponse -= HandleSimpleResponse;
  119. ReceivedResponse_SimpleReject -= HandleSimpleReject;
  120. ReceivedResponse_SimpleNotify -= HandleSimpleNotify;
  121. _tcpProtoClient.Dispose();
  122. }
  123. public bool ConnectAndStart() { return _tcpProtoClient.ConnectAndStart(); }
  124. public bool DisconnectAndStop() { return _tcpProtoClient.DisconnectAndStop(); }
  125. public bool Reconnect() { return _tcpProtoClient.Reconnect(); }
  126. private bool _watchdog;
  127. private Thread _watchdogThread;
  128. public bool StartWatchdog()
  129. {
  130. if (_watchdog)
  131. return false;
  132. Console.WriteLine("Watchdog thread starting...");
  133. // Start the watchdog thread
  134. _watchdog = true;
  135. _watchdogThread = new Thread(WatchdogThread);
  136. Console.WriteLine("Watchdog thread started!");
  137. return true;
  138. }
  139. public bool StopWatchdog()
  140. {
  141. if (!_watchdog)
  142. return false;
  143. Console.WriteLine("Watchdog thread stopping...");
  144. // Stop the watchdog thread
  145. _watchdog = false;
  146. _watchdogThread.Join();
  147. Console.WriteLine("Watchdog thread stopped!");
  148. return true;
  149. }
  150. public static void WatchdogThread(object obj)
  151. {
  152. var instance = obj as SimpleProtoClient;
  153. if (instance == null)
  154. return;
  155. try
  156. {
  157. // Watchdog loop...
  158. while (instance._watchdog)
  159. {
  160. var utc = DateTime.UtcNow;
  161. // Watchdog the client
  162. instance.Watchdog(utc);
  163. // Sleep for a while...
  164. Thread.Sleep(1000);
  165. }
  166. }
  167. catch (Exception e)
  168. {
  169. Console.WriteLine($"Config client watchdog thread terminated: {e}");
  170. }
  171. }
  172. #region Connection handlers
  173. public delegate void ConnectedHandler();
  174. public event ConnectedHandler Connected = () => {};
  175. private void OnConnected()
  176. {
  177. // Reset FBE protocol buffers
  178. Reset();
  179. Connected?.Invoke();
  180. }
  181. public delegate void DisconnectedHandler();
  182. public event DisconnectedHandler Disconnected = () => {};
  183. private void OnDisconnected()
  184. {
  185. Disconnected?.Invoke();
  186. }
  187. public long OnSend(byte[] buffer, long offset, long size)
  188. {
  189. return _tcpProtoClient.SendAsync(buffer, offset, size) ? size : 0;
  190. }
  191. public void OnReceived(byte[] buffer, long offset, long size)
  192. {
  193. Receive(buffer, offset, size);
  194. }
  195. #endregion
  196. #region Protocol handlers
  197. private void HandleDisconnectRequest(DisconnectRequest request) { Console.WriteLine($"Received: {request}"); _tcpProtoClient.DisconnectAsync(); }
  198. private void HandleSimpleResponse(SimpleResponse response) { Console.WriteLine($"Received: {response}"); }
  199. private void HandleSimpleReject(SimpleReject reject) { Console.WriteLine($"Received: {reject}"); }
  200. private void HandleSimpleNotify(SimpleNotify notify) { Console.WriteLine($"Received: {notify}"); }
  201. #endregion
  202. #region IDisposable implementation
  203. // Disposed flag.
  204. private bool _disposed;
  205. // Implement IDisposable.
  206. public void Dispose()
  207. {
  208. Dispose(true);
  209. GC.SuppressFinalize(this);
  210. }
  211. protected virtual void Dispose(bool disposingManagedResources)
  212. {
  213. // The idea here is that Dispose(Boolean) knows whether it is
  214. // being called to do explicit cleanup (the Boolean is true)
  215. // versus being called due to a garbage collection (the Boolean
  216. // is false). This distinction is useful because, when being
  217. // disposed explicitly, the Dispose(Boolean) method can safely
  218. // execute code using reference type fields that refer to other
  219. // objects knowing for sure that these other objects have not been
  220. // finalized or disposed of yet. When the Boolean is false,
  221. // the Dispose(Boolean) method should not execute code that
  222. // refer to reference type fields because those objects may
  223. // have already been finalized."
  224. if (!_disposed)
  225. {
  226. if (disposingManagedResources)
  227. {
  228. // Dispose managed resources here...
  229. DisposeClient();
  230. }
  231. // Dispose unmanaged resources here...
  232. // Set large fields to null here...
  233. // Mark as disposed.
  234. _disposed = true;
  235. }
  236. }
  237. #endregion
  238. }
  239. class Program
  240. {
  241. static void Main(string[] args)
  242. {
  243. // Simple protocol server address
  244. string address = "127.0.0.1";
  245. if (args.Length > 0)
  246. address = args[0];
  247. // Simple protocol server port
  248. int port = 4444;
  249. if (args.Length > 1)
  250. port = int.Parse(args[1]);
  251. Console.WriteLine($"Simple protocol server address: {address}");
  252. Console.WriteLine($"Simple protocol server port: {port}");
  253. Console.WriteLine();
  254. // Create a new simple protocol chat client
  255. var client = new SimpleProtoClient(address, port);
  256. // Connect the client
  257. Console.Write("Client connecting...");
  258. client.ConnectAndStart();
  259. Console.WriteLine("Done!");
  260. Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");
  261. // Perform text input
  262. for (;;)
  263. {
  264. string line = Console.ReadLine();
  265. if (string.IsNullOrEmpty(line))
  266. break;
  267. // Disconnect the client
  268. if (line == "!")
  269. {
  270. Console.Write("Client disconnecting...");
  271. client.Reconnect();
  272. Console.WriteLine("Done!");
  273. continue;
  274. }
  275. // Send request to the simple protocol server
  276. SimpleRequest request = SimpleRequest.Default;
  277. request.Message = line;
  278. var response = client.Request(request).Result;
  279. // Show string hash calculation result
  280. Console.WriteLine($"Hash of '{line}' = 0x{response.Hash:X8}");
  281. }
  282. // Disconnect the client
  283. Console.Write("Client disconnecting...");
  284. client.DisconnectAndStop();
  285. Console.WriteLine("Done!");
  286. }
  287. }
  288. }

Example: HTTP server

Here comes the example of the HTTP cache server. It allows to manipulate
cache data with HTTP methods (GET, POST, PUT and DELETE).

Use the following link to open Swagger OpenAPI iterative documentation: http://localhost:8080/api/index.html

OpenAPI-HTTP

  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Net;
  4. using System.Net.Sockets;
  5. using System.Text;
  6. using NetCoreServer;
  7. namespace HttpServer
  8. {
  9. class CommonCache
  10. {
  11. public static CommonCache GetInstance()
  12. {
  13. if (_instance == null)
  14. _instance = new CommonCache();
  15. return _instance;
  16. }
  17. public string GetAllCache()
  18. {
  19. var result = new StringBuilder();
  20. result.Append("[\n");
  21. foreach (var item in _cache)
  22. {
  23. result.Append(" {\n");
  24. result.AppendFormat($" \"key\": \"{item.Key}\",\n");
  25. result.AppendFormat($" \"value\": \"{item.Value}\",\n");
  26. result.Append(" },\n");
  27. }
  28. result.Append("]\n");
  29. return result.ToString();
  30. }
  31. public bool GetCacheValue(string key, out string value)
  32. {
  33. return _cache.TryGetValue(key, out value);
  34. }
  35. public void PutCacheValue(string key, string value)
  36. {
  37. _cache[key] = value;
  38. }
  39. public bool DeleteCacheValue(string key, out string value)
  40. {
  41. return _cache.TryRemove(key, out value);
  42. }
  43. private readonly ConcurrentDictionary<string, string> _cache = new ConcurrentDictionary<string, string>();
  44. private static CommonCache _instance;
  45. }
  46. class HttpCacheSession : HttpSession
  47. {
  48. public HttpCacheSession(NetCoreServer.HttpServer server) : base(server) {}
  49. protected override void OnReceivedRequest(HttpRequest request)
  50. {
  51. // Show HTTP request content
  52. Console.WriteLine(request);
  53. // Process HTTP request methods
  54. if (request.Method == "HEAD")
  55. SendResponseAsync(Response.MakeHeadResponse());
  56. else if (request.Method == "GET")
  57. {
  58. string key = request.Url;
  59. // Decode the key value
  60. key = Uri.UnescapeDataString(key);
  61. key = key.Replace("/api/cache", "", StringComparison.InvariantCultureIgnoreCase);
  62. key = key.Replace("?key=", "", StringComparison.InvariantCultureIgnoreCase);
  63. if (string.IsNullOrEmpty(key))
  64. {
  65. // Response with all cache values
  66. SendResponseAsync(Response.MakeGetResponse(CommonCache.GetInstance().GetAllCache(), "application/json; charset=UTF-8"));
  67. }
  68. // Get the cache value by the given key
  69. else if (CommonCache.GetInstance().GetCacheValue(key, out var value))
  70. {
  71. // Response with the cache value
  72. SendResponseAsync(Response.MakeGetResponse(value));
  73. }
  74. else
  75. SendResponseAsync(Response.MakeErrorResponse(404, "Required cache value was not found for the key: " + key));
  76. }
  77. else if ((request.Method == "POST") || (request.Method == "PUT"))
  78. {
  79. string key = request.Url;
  80. string value = request.Body;
  81. // Decode the key value
  82. key = Uri.UnescapeDataString(key);
  83. key = key.Replace("/api/cache", "", StringComparison.InvariantCultureIgnoreCase);
  84. key = key.Replace("?key=", "", StringComparison.InvariantCultureIgnoreCase);
  85. // Put the cache value
  86. CommonCache.GetInstance().PutCacheValue(key, value);
  87. // Response with the cache value
  88. SendResponseAsync(Response.MakeOkResponse());
  89. }
  90. else if (request.Method == "DELETE")
  91. {
  92. string key = request.Url;
  93. // Decode the key value
  94. key = Uri.UnescapeDataString(key);
  95. key = key.Replace("/api/cache", "", StringComparison.InvariantCultureIgnoreCase);
  96. key = key.Replace("?key=", "", StringComparison.InvariantCultureIgnoreCase);
  97. // Delete the cache value
  98. if (CommonCache.GetInstance().DeleteCacheValue(key, out var value))
  99. {
  100. // Response with the cache value
  101. SendResponseAsync(Response.MakeGetResponse(value));
  102. }
  103. else
  104. SendResponseAsync(Response.MakeErrorResponse(404, "Deleted cache value was not found for the key: " + key));
  105. }
  106. else if (request.Method == "OPTIONS")
  107. SendResponseAsync(Response.MakeOptionsResponse());
  108. else if (request.Method == "TRACE")
  109. SendResponseAsync(Response.MakeTraceResponse(request.Cache.Data));
  110. else
  111. SendResponseAsync(Response.MakeErrorResponse("Unsupported HTTP method: " + request.Method));
  112. }
  113. protected override void OnReceivedRequestError(HttpRequest request, string error)
  114. {
  115. Console.WriteLine($"Request error: {error}");
  116. }
  117. protected override void OnError(SocketError error)
  118. {
  119. Console.WriteLine($"HTTP session caught an error: {error}");
  120. }
  121. }
  122. class HttpCacheServer : NetCoreServer.HttpServer
  123. {
  124. public HttpCacheServer(IPAddress address, int port) : base(address, port) {}
  125. protected override TcpSession CreateSession() { return new HttpCacheSession(this); }
  126. protected override void OnError(SocketError error)
  127. {
  128. Console.WriteLine($"HTTP session caught an error: {error}");
  129. }
  130. }
  131. class Program
  132. {
  133. static void Main(string[] args)
  134. {
  135. // HTTP server port
  136. int port = 8080;
  137. if (args.Length > 0)
  138. port = int.Parse(args[0]);
  139. // HTTP server content path
  140. string www = "../../../../../www/api";
  141. if (args.Length > 1)
  142. www = args[1];
  143. Console.WriteLine($"HTTP server port: {port}");
  144. Console.WriteLine($"HTTP server static content path: {www}");
  145. Console.WriteLine($"HTTP server website: http://localhost:{port}/api/index.html");
  146. Console.WriteLine();
  147. // Create a new HTTP server
  148. var server = new HttpCacheServer(IPAddress.Any, port);
  149. server.AddStaticContent(www, "/api");
  150. // Start the server
  151. Console.Write("Server starting...");
  152. server.Start();
  153. Console.WriteLine("Done!");
  154. Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");
  155. // Perform text input
  156. for (;;)
  157. {
  158. string line = Console.ReadLine();
  159. if (string.IsNullOrEmpty(line))
  160. break;
  161. // Restart the server
  162. if (line == "!")
  163. {
  164. Console.Write("Server restarting...");
  165. server.Restart();
  166. Console.WriteLine("Done!");
  167. }
  168. }
  169. // Stop the server
  170. Console.Write("Server stopping...");
  171. server.Stop();
  172. Console.WriteLine("Done!");
  173. }
  174. }
  175. }

Example: HTTP client

Here comes the example of the HTTP client. It allows to send HTTP requests
(GET, POST, PUT and DELETE) and receive HTTP responses.

  1. using System;
  2. using NetCoreServer;
  3. namespace HttpClient
  4. {
  5. class Program
  6. {
  7. static void Main(string[] args)
  8. {
  9. // HTTP server address
  10. string address = "127.0.0.1";
  11. if (args.Length > 0)
  12. address = args[0];
  13. // HTTP server port
  14. int port = 8080;
  15. if (args.Length > 1)
  16. port = int.Parse(args[1]);
  17. Console.WriteLine($"HTTP server address: {address}");
  18. Console.WriteLine($"HTTP server port: {port}");
  19. Console.WriteLine();
  20. // Create a new HTTP client
  21. var client = new HttpClientEx(address, port);
  22. Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");
  23. // Perform text input
  24. for (;;)
  25. {
  26. string line = Console.ReadLine();
  27. if (string.IsNullOrEmpty(line))
  28. break;
  29. // Reconnect the client
  30. if (line == "!")
  31. {
  32. Console.Write("Client reconnecting...");
  33. if (client.IsConnected)
  34. client.ReconnectAsync();
  35. else
  36. client.ConnectAsync();
  37. Console.WriteLine("Done!");
  38. continue;
  39. }
  40. var commands = line.Split(' ');
  41. if (commands.Length < 2)
  42. {
  43. Console.WriteLine("HTTP method and URL must be entered!");
  44. continue;
  45. }
  46. if (commands[0].ToUpper() == "HEAD")
  47. {
  48. var response = client.SendHeadRequest(commands[1]).Result;
  49. Console.WriteLine(response);
  50. }
  51. else if (commands[0].ToUpper() == "GET")
  52. {
  53. var response = client.SendGetRequest(commands[1]).Result;
  54. Console.WriteLine(response);
  55. }
  56. else if (commands[0].ToUpper() == "POST")
  57. {
  58. if (commands.Length < 3)
  59. {
  60. Console.WriteLine("HTTP method, URL and body must be entered!");
  61. continue;
  62. }
  63. var response = client.SendPostRequest(commands[1], commands[2]).Result;
  64. Console.WriteLine(response);
  65. }
  66. else if (commands[0].ToUpper() == "PUT")
  67. {
  68. if (commands.Length < 3)
  69. {
  70. Console.WriteLine("HTTP method, URL and body must be entered!");
  71. continue;
  72. }
  73. var response = client.SendPutRequest(commands[1], commands[2]).Result;
  74. Console.WriteLine(response);
  75. }
  76. else if (commands[0].ToUpper() == "DELETE")
  77. {
  78. var response = client.SendDeleteRequest(commands[1]).Result;
  79. Console.WriteLine(response);
  80. }
  81. else if (commands[0].ToUpper() == "OPTIONS")
  82. {
  83. var response = client.SendOptionsRequest(commands[1]).Result;
  84. Console.WriteLine(response);
  85. }
  86. else if (commands[0].ToUpper() == "TRACE")
  87. {
  88. var response = client.SendTraceRequest(commands[1]).Result;
  89. Console.WriteLine(response);
  90. }
  91. else
  92. Console.WriteLine("Unknown HTTP method");
  93. }
  94. // Disconnect the client
  95. Console.Write("Client disconnecting...");
  96. client.Disconnect();
  97. Console.WriteLine("Done!");
  98. }
  99. }
  100. }

Example: HTTPS server

Here comes the example of the HTTPS cache server. It allows to manipulate
cache data with HTTP methods (GET, POST, PUT and DELETE) with secured
transport protocol.

Use the following link to open Swagger OpenAPI iterative documentation: https://localhost:8443/api/index.html

OpenAPI-HTTPS

  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Net;
  4. using System.Net.Sockets;
  5. using System.Security.Authentication;
  6. using System.Security.Cryptography.X509Certificates;
  7. using System.Text;
  8. using NetCoreServer;
  9. namespace HttpsServer
  10. {
  11. class CommonCache
  12. {
  13. public static CommonCache GetInstance()
  14. {
  15. if (_instance == null)
  16. _instance = new CommonCache();
  17. return _instance;
  18. }
  19. public string GetAllCache()
  20. {
  21. var result = new StringBuilder();
  22. result.Append("[\n");
  23. foreach (var item in _cache)
  24. {
  25. result.Append(" {\n");
  26. result.AppendFormat($" \"key\": \"{item.Key}\",\n");
  27. result.AppendFormat($" \"value\": \"{item.Value}\",\n");
  28. result.Append(" },\n");
  29. }
  30. result.Append("]\n");
  31. return result.ToString();
  32. }
  33. public bool GetCacheValue(string key, out string value)
  34. {
  35. return _cache.TryGetValue(key, out value);
  36. }
  37. public void PutCacheValue(string key, string value)
  38. {
  39. _cache[key] = value;
  40. }
  41. public bool DeleteCacheValue(string key, out string value)
  42. {
  43. return _cache.TryRemove(key, out value);
  44. }
  45. private readonly ConcurrentDictionary<string, string> _cache = new ConcurrentDictionary<string, string>();
  46. private static CommonCache _instance;
  47. }
  48. class HttpsCacheSession : HttpsSession
  49. {
  50. public HttpsCacheSession(NetCoreServer.HttpsServer server) : base(server) {}
  51. protected override void OnReceivedRequest(HttpRequest request)
  52. {
  53. // Show HTTP request content
  54. Console.WriteLine(request);
  55. // Process HTTP request methods
  56. if (request.Method == "HEAD")
  57. SendResponseAsync(Response.MakeHeadResponse());
  58. else if (request.Method == "GET")
  59. {
  60. string key = request.Url;
  61. // Decode the key value
  62. key = Uri.UnescapeDataString(key);
  63. key = key.Replace("/api/cache", "", StringComparison.InvariantCultureIgnoreCase);
  64. key = key.Replace("?key=", "", StringComparison.InvariantCultureIgnoreCase);
  65. if (string.IsNullOrEmpty(key))
  66. {
  67. // Response with all cache values
  68. SendResponseAsync(Response.MakeGetResponse(CommonCache.GetInstance().GetAllCache(), "application/json; charset=UTF-8"));
  69. }
  70. // Get the cache value by the given key
  71. else if (CommonCache.GetInstance().GetCacheValue(key, out var value))
  72. {
  73. // Response with the cache value
  74. SendResponseAsync(Response.MakeGetResponse(value));
  75. }
  76. else
  77. SendResponseAsync(Response.MakeErrorResponse(404, "Required cache value was not found for the key: " + key));
  78. }
  79. else if ((request.Method == "POST") || (request.Method == "PUT"))
  80. {
  81. string key = request.Url;
  82. string value = request.Body;
  83. // Decode the key value
  84. key = Uri.UnescapeDataString(key);
  85. key = key.Replace("/api/cache", "", StringComparison.InvariantCultureIgnoreCase);
  86. key = key.Replace("?key=", "", StringComparison.InvariantCultureIgnoreCase);
  87. // Put the cache value
  88. CommonCache.GetInstance().PutCacheValue(key, value);
  89. // Response with the cache value
  90. SendResponseAsync(Response.MakeOkResponse());
  91. }
  92. else if (request.Method == "DELETE")
  93. {
  94. string key = request.Url;
  95. // Decode the key value
  96. key = Uri.UnescapeDataString(key);
  97. key = key.Replace("/api/cache", "", StringComparison.InvariantCultureIgnoreCase);
  98. key = key.Replace("?key=", "", StringComparison.InvariantCultureIgnoreCase);
  99. // Delete the cache value
  100. if (CommonCache.GetInstance().DeleteCacheValue(key, out var value))
  101. {
  102. // Response with the cache value
  103. SendResponseAsync(Response.MakeGetResponse(value));
  104. }
  105. else
  106. SendResponseAsync(Response.MakeErrorResponse(404, "Deleted cache value was not found for the key: " + key));
  107. }
  108. else if (request.Method == "OPTIONS")
  109. SendResponseAsync(Response.MakeOptionsResponse());
  110. else if (request.Method == "TRACE")
  111. SendResponseAsync(Response.MakeTraceResponse(request.Cache));
  112. else
  113. SendResponseAsync(Response.MakeErrorResponse("Unsupported HTTP method: " + request.Method));
  114. }
  115. protected override void OnReceivedRequestError(HttpRequest request, string error)
  116. {
  117. Console.WriteLine($"Request error: {error}");
  118. }
  119. protected override void OnError(SocketError error)
  120. {
  121. Console.WriteLine($"HTTPS session caught an error: {error}");
  122. }
  123. }
  124. class HttpsCacheServer : NetCoreServer.HttpsServer
  125. {
  126. public HttpsCacheServer(SslContext context, IPAddress address, int port) : base(context, address, port) {}
  127. protected override SslSession CreateSession() { return new HttpsCacheSession(this); }
  128. protected override void OnError(SocketError error)
  129. {
  130. Console.WriteLine($"HTTPS server caught an error: {error}");
  131. }
  132. }
  133. class Program
  134. {
  135. static void Main(string[] args)
  136. {
  137. // HTTPS server port
  138. int port = 8443;
  139. if (args.Length > 0)
  140. port = int.Parse(args[0]);
  141. // HTTPS server content path
  142. string www = "../../../../../www/api";
  143. if (args.Length > 1)
  144. www = args[1];
  145. Console.WriteLine($"HTTPS server port: {port}");
  146. Console.WriteLine($"HTTPS server static content path: {www}");
  147. Console.WriteLine($"HTTPS server website: https://localhost:{port}/api/index.html");
  148. Console.WriteLine();
  149. // Create and prepare a new SSL server context
  150. var context = new SslContext(SslProtocols.Tls12, new X509Certificate2("server.pfx", "qwerty"));
  151. // Create a new HTTP server
  152. var server = new HttpsCacheServer(context, IPAddress.Any, port);
  153. server.AddStaticContent(www, "/api");
  154. // Start the server
  155. Console.Write("Server starting...");
  156. server.Start();
  157. Console.WriteLine("Done!");
  158. Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");
  159. // Perform text input
  160. for (;;)
  161. {
  162. string line = Console.ReadLine();
  163. if (string.IsNullOrEmpty(line))
  164. break;
  165. // Restart the server
  166. if (line == "!")
  167. {
  168. Console.Write("Server restarting...");
  169. server.Restart();
  170. Console.WriteLine("Done!");
  171. }
  172. }
  173. // Stop the server
  174. Console.Write("Server stopping...");
  175. server.Stop();
  176. Console.WriteLine("Done!");
  177. }
  178. }
  179. }

Example: HTTPS client

Here comes the example of the HTTPS client. It allows to send HTTP requests
(GET, POST, PUT and DELETE) and receive HTTP responses with secured
transport protocol.

  1. using System;
  2. using System.Security.Authentication;
  3. using System.Security.Cryptography.X509Certificates;
  4. using NetCoreServer;
  5. namespace HttpsClient
  6. {
  7. class Program
  8. {
  9. static void Main(string[] args)
  10. {
  11. // HTTPS server address
  12. string address = "127.0.0.1";
  13. if (args.Length > 0)
  14. address = args[0];
  15. // HTTPS server port
  16. int port = 8443;
  17. if (args.Length > 1)
  18. port = int.Parse(args[1]);
  19. Console.WriteLine($"HTTPS server address: {address}");
  20. Console.WriteLine($"HTTPS server port: {port}");
  21. Console.WriteLine();
  22. // Create and prepare a new SSL client context
  23. var context = new SslContext(SslProtocols.Tls12, new X509Certificate2("client.pfx", "qwerty"), (sender, certificate, chain, sslPolicyErrors) => true);
  24. // Create a new HTTPS client
  25. var client = new HttpsClientEx(context, address, port);
  26. Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");
  27. // Perform text input
  28. for (;;)
  29. {
  30. string line = Console.ReadLine();
  31. if (string.IsNullOrEmpty(line))
  32. break;
  33. // Reconnect the client
  34. if (line == "!")
  35. {
  36. Console.Write("Client reconnecting...");
  37. if (client.IsConnected)
  38. client.ReconnectAsync();
  39. else
  40. client.ConnectAsync();
  41. Console.WriteLine("Done!");
  42. continue;
  43. }
  44. var commands = line.Split(' ');
  45. if (commands.Length < 2)
  46. {
  47. Console.WriteLine("HTTP method and URL must be entered!");
  48. continue;
  49. }
  50. if (commands[0].ToUpper() == "HEAD")
  51. {
  52. var response = client.SendHeadRequest(commands[1]).Result;
  53. Console.WriteLine(response);
  54. }
  55. else if (commands[0].ToUpper() == "GET")
  56. {
  57. var response = client.SendGetRequest(commands[1]).Result;
  58. Console.WriteLine(response);
  59. }
  60. else if (commands[0].ToUpper() == "POST")
  61. {
  62. if (commands.Length < 3)
  63. {
  64. Console.WriteLine("HTTP method, URL and body must be entered!");
  65. continue;
  66. }
  67. var response = client.SendPostRequest(commands[1], commands[2]).Result;
  68. Console.WriteLine(response);
  69. }
  70. else if (commands[0].ToUpper() == "PUT")
  71. {
  72. if (commands.Length < 3)
  73. {
  74. Console.WriteLine("HTTP method, URL and body must be entered!");
  75. continue;
  76. }
  77. var response = client.SendPutRequest(commands[1], commands[2]).Result;
  78. Console.WriteLine(response);
  79. }
  80. else if (commands[0].ToUpper() == "DELETE")
  81. {
  82. var response = client.SendDeleteRequest(commands[1]).Result;
  83. Console.WriteLine(response);
  84. }
  85. else if (commands[0].ToUpper() == "OPTIONS")
  86. {
  87. var response = client.SendOptionsRequest(commands[1]).Result;
  88. Console.WriteLine(response);
  89. }
  90. else if (commands[0].ToUpper() == "TRACE")
  91. {
  92. var response = client.SendTraceRequest(commands[1]).Result;
  93. Console.WriteLine(response);
  94. }
  95. else
  96. Console.WriteLine("Unknown HTTP method");
  97. }
  98. // Disconnect the client
  99. Console.Write("Client disconnecting...");
  100. client.Disconnect();
  101. Console.WriteLine("Done!");
  102. }
  103. }
  104. }

Example: WebSocket chat server

Here comes the example of the WebSocket chat server. It handles multiple
WebSocket client sessions and multicast received message from any session
to all ones. Also it is possible to send admin message directly from the
server.

Use the following link to open WebSocket chat server example: http://localhost:8080/chat/index.html

ws-chat

  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.Text;
  5. using NetCoreServer;
  6. namespace WsChatServer
  7. {
  8. class ChatSession : WsSession
  9. {
  10. public ChatSession(WsServer server) : base(server) {}
  11. public override void OnWsConnected(HttpRequest request)
  12. {
  13. Console.WriteLine($"Chat WebSocket session with Id {Id} connected!");
  14. // Send invite message
  15. string message = "Hello from WebSocket chat! Please send a message or '!' to disconnect the client!";
  16. SendTextAsync(message);
  17. }
  18. public override void OnWsDisconnected()
  19. {
  20. Console.WriteLine($"Chat WebSocket session with Id {Id} disconnected!");
  21. }
  22. public override void OnWsReceived(byte[] buffer, long offset, long size)
  23. {
  24. string message = Encoding.UTF8.GetString(buffer, (int)offset, (int)size);
  25. Console.WriteLine("Incoming: " + message);
  26. // Multicast message to all connected sessions
  27. ((WsServer)Server).MulticastText(message);
  28. // If the buffer starts with '!' the disconnect the current session
  29. if (message == "!")
  30. Close(1000);
  31. }
  32. protected override void OnError(SocketError error)
  33. {
  34. Console.WriteLine($"Chat WebSocket session caught an error with code {error}");
  35. }
  36. }
  37. class ChatServer : WsServer
  38. {
  39. public ChatServer(IPAddress address, int port) : base(address, port) {}
  40. protected override TcpSession CreateSession() { return new ChatSession(this); }
  41. protected override void OnError(SocketError error)
  42. {
  43. Console.WriteLine($"Chat WebSocket server caught an error with code {error}");
  44. }
  45. }
  46. class Program
  47. {
  48. static void Main(string[] args)
  49. {
  50. // WebSocket server port
  51. int port = 8080;
  52. if (args.Length > 0)
  53. port = int.Parse(args[0]);
  54. // WebSocket server content path
  55. string www = "../../../../../www/ws";
  56. if (args.Length > 1)
  57. www = args[1];
  58. Console.WriteLine($"WebSocket server port: {port}");
  59. Console.WriteLine($"WebSocket server static content path: {www}");
  60. Console.WriteLine($"WebSocket server website: http://localhost:{port}/chat/index.html");
  61. Console.WriteLine();
  62. // Create a new WebSocket server
  63. var server = new ChatServer(IPAddress.Any, port);
  64. server.AddStaticContent(www, "/chat");
  65. // Start the server
  66. Console.Write("Server starting...");
  67. server.Start();
  68. Console.WriteLine("Done!");
  69. Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");
  70. // Perform text input
  71. for (;;)
  72. {
  73. string line = Console.ReadLine();
  74. if (string.IsNullOrEmpty(line))
  75. break;
  76. // Restart the server
  77. if (line == "!")
  78. {
  79. Console.Write("Server restarting...");
  80. server.Restart();
  81. Console.WriteLine("Done!");
  82. }
  83. // Multicast admin message to all sessions
  84. line = "(admin) " + line;
  85. server.MulticastText(line);
  86. }
  87. // Stop the server
  88. Console.Write("Server stopping...");
  89. server.Stop();
  90. Console.WriteLine("Done!");
  91. }
  92. }
  93. }

Example: WebSocket chat client

Here comes the example of the WebSocket chat client. It connects to the
WebSocket chat server and allows to send message to it and receive new
messages.

  1. using System;
  2. using System.Net.Sockets;
  3. using System.Text;
  4. using System.Threading;
  5. using NetCoreServer;
  6. namespace WsChatClient
  7. {
  8. class ChatClient : WsClient
  9. {
  10. public ChatClient(string address, int port) : base(address, port) {}
  11. public void DisconnectAndStop()
  12. {
  13. _stop = true;
  14. CloseAsync(1000);
  15. while (IsConnected)
  16. Thread.Yield();
  17. }
  18. public override void OnWsConnecting(HttpRequest request)
  19. {
  20. request.SetBegin("GET", "/");
  21. request.SetHeader("Host", "localhost");
  22. request.SetHeader("Origin", "http://localhost");
  23. request.SetHeader("Upgrade", "websocket");
  24. request.SetHeader("Connection", "Upgrade");
  25. request.SetHeader("Sec-WebSocket-Key", Convert.ToBase64String(WsNonce));
  26. request.SetHeader("Sec-WebSocket-Protocol", "chat, superchat");
  27. request.SetHeader("Sec-WebSocket-Version", "13");
  28. request.SetBody();
  29. }
  30. public override void OnWsConnected(HttpResponse response)
  31. {
  32. Console.WriteLine($"Chat WebSocket client connected a new session with Id {Id}");
  33. }
  34. public override void OnWsDisconnected()
  35. {
  36. Console.WriteLine($"Chat WebSocket client disconnected a session with Id {Id}");
  37. }
  38. public override void OnWsReceived(byte[] buffer, long offset, long size)
  39. {
  40. Console.WriteLine($"Incoming: {Encoding.UTF8.GetString(buffer, (int)offset, (int)size)}");
  41. }
  42. protected override void OnDisconnected()
  43. {
  44. base.OnDisconnected();
  45. Console.WriteLine($"Chat WebSocket client disconnected a session with Id {Id}");
  46. // Wait for a while...
  47. Thread.Sleep(1000);
  48. // Try to connect again
  49. if (!_stop)
  50. ConnectAsync();
  51. }
  52. protected override void OnError(SocketError error)
  53. {
  54. Console.WriteLine($"Chat WebSocket client caught an error with code {error}");
  55. }
  56. private bool _stop;
  57. }
  58. class Program
  59. {
  60. static void Main(string[] args)
  61. {
  62. // WebSocket server address
  63. string address = "127.0.0.1";
  64. if (args.Length > 0)
  65. address = args[0];
  66. // WebSocket server port
  67. int port = 8080;
  68. if (args.Length > 1)
  69. port = int.Parse(args[1]);
  70. Console.WriteLine($"WebSocket server address: {address}");
  71. Console.WriteLine($"WebSocket server port: {port}");
  72. Console.WriteLine();
  73. // Create a new TCP chat client
  74. var client = new ChatClient(address, port);
  75. // Connect the client
  76. Console.Write("Client connecting...");
  77. client.ConnectAsync();
  78. Console.WriteLine("Done!");
  79. Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");
  80. // Perform text input
  81. for (;;)
  82. {
  83. string line = Console.ReadLine();
  84. if (string.IsNullOrEmpty(line))
  85. break;
  86. // Disconnect the client
  87. if (line == "!")
  88. {
  89. Console.Write("Client disconnecting...");
  90. client.DisconnectAsync();
  91. Console.WriteLine("Done!");
  92. continue;
  93. }
  94. // Send the entered text to the chat server
  95. client.SendTextAsync(line);
  96. }
  97. // Disconnect the client
  98. Console.Write("Client disconnecting...");
  99. client.DisconnectAndStop();
  100. Console.WriteLine("Done!");
  101. }
  102. }
  103. }

Example: WebSocket secure chat server

Here comes the example of the WebSocket secure chat server. It handles
multiple WebSocket secure client sessions and multicast received message
from any session to all ones. Also it is possible to send admin message
directly from the server.

This example is very similar to the WebSocket one except the code that
prepares WebSocket secure context and handshake handler.

Use the following link to open WebSocket secure chat server example: https://localhost:8443/chat/index.html

wss-chat

  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.Security.Authentication;
  5. using System.Security.Cryptography.X509Certificates;
  6. using System.Text;
  7. using NetCoreServer;
  8. namespace WssChatServer
  9. {
  10. class ChatSession : WssSession
  11. {
  12. public ChatSession(WssServer server) : base(server) {}
  13. public override void OnWsConnected(HttpRequest request)
  14. {
  15. Console.WriteLine($"Chat WebSocket session with Id {Id} connected!");
  16. // Send invite message
  17. string message = "Hello from WebSocket chat! Please send a message or '!' to disconnect the client!";
  18. SendTextAsync(message);
  19. }
  20. public override void OnWsDisconnected()
  21. {
  22. Console.WriteLine($"Chat WebSocket session with Id {Id} disconnected!");
  23. }
  24. public override void OnWsReceived(byte[] buffer, long offset, long size)
  25. {
  26. string message = Encoding.UTF8.GetString(buffer, (int)offset, (int)size);
  27. Console.WriteLine("Incoming: " + message);
  28. // Multicast message to all connected sessions
  29. ((WssServer)Server).MulticastText(message);
  30. // If the buffer starts with '!' the disconnect the current session
  31. if (message == "!")
  32. Close(1000);
  33. }
  34. protected override void OnError(SocketError error)
  35. {
  36. Console.WriteLine($"Chat WebSocket session caught an error with code {error}");
  37. }
  38. }
  39. class ChatServer : WssServer
  40. {
  41. public ChatServer(SslContext context, IPAddress address, int port) : base(context, address, port) {}
  42. protected override SslSession CreateSession() { return new ChatSession(this); }
  43. protected override void OnError(SocketError error)
  44. {
  45. Console.WriteLine($"Chat WebSocket server caught an error with code {error}");
  46. }
  47. }
  48. class Program
  49. {
  50. static void Main(string[] args)
  51. {
  52. // WebSocket server port
  53. int port = 8443;
  54. if (args.Length > 0)
  55. port = int.Parse(args[0]);
  56. // WebSocket server content path
  57. string www = "../../../../../www/wss";
  58. if (args.Length > 1)
  59. www = args[1];
  60. Console.WriteLine($"WebSocket server port: {port}");
  61. Console.WriteLine($"WebSocket server static content path: {www}");
  62. Console.WriteLine($"WebSocket server website: https://localhost:{port}/chat/index.html");
  63. Console.WriteLine();
  64. // Create and prepare a new SSL server context
  65. var context = new SslContext(SslProtocols.Tls12, new X509Certificate2("server.pfx", "qwerty"));
  66. // Create a new WebSocket server
  67. var server = new ChatServer(context, IPAddress.Any, port);
  68. server.AddStaticContent(www, "/chat");
  69. // Start the server
  70. Console.Write("Server starting...");
  71. server.Start();
  72. Console.WriteLine("Done!");
  73. Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");
  74. // Perform text input
  75. for (;;)
  76. {
  77. string line = Console.ReadLine();
  78. if (string.IsNullOrEmpty(line))
  79. break;
  80. // Restart the server
  81. if (line == "!")
  82. {
  83. Console.Write("Server restarting...");
  84. server.Restart();
  85. Console.WriteLine("Done!");
  86. }
  87. // Multicast admin message to all sessions
  88. line = "(admin) " + line;
  89. server.MulticastText(line);
  90. }
  91. // Stop the server
  92. Console.Write("Server stopping...");
  93. server.Stop();
  94. Console.WriteLine("Done!");
  95. }
  96. }
  97. }

Example: WebSocket secure chat client

Here comes the example of the WebSocket secure chat client. It connects to
the WebSocket secure chat server and allows to send message to it and receive
new messages.

This example is very similar to the WebSocket one except the code that
prepares WebSocket secure context and handshake handler.

  1. using System;
  2. using System.Net.Sockets;
  3. using System.Security.Authentication;
  4. using System.Security.Cryptography.X509Certificates;
  5. using System.Text;
  6. using System.Threading;
  7. using NetCoreServer;
  8. namespace WssChatClient
  9. {
  10. class ChatClient : WssClient
  11. {
  12. public ChatClient(SslContext context, string address, int port) : base(context, address, port) {}
  13. public void DisconnectAndStop()
  14. {
  15. _stop = true;
  16. CloseAsync(1000);
  17. while (IsConnected)
  18. Thread.Yield();
  19. }
  20. public override void OnWsConnecting(HttpRequest request)
  21. {
  22. request.SetBegin("GET", "/");
  23. request.SetHeader("Host", "localhost");
  24. request.SetHeader("Origin", "http://localhost");
  25. request.SetHeader("Upgrade", "websocket");
  26. request.SetHeader("Connection", "Upgrade");
  27. request.SetHeader("Sec-WebSocket-Key", Convert.ToBase64String(WsNonce));
  28. request.SetHeader("Sec-WebSocket-Protocol", "chat, superchat");
  29. request.SetHeader("Sec-WebSocket-Version", "13");
  30. request.SetBody();
  31. }
  32. public override void OnWsConnected(HttpResponse response)
  33. {
  34. Console.WriteLine($"Chat WebSocket client connected a new session with Id {Id}");
  35. }
  36. public override void OnWsDisconnected()
  37. {
  38. Console.WriteLine($"Chat WebSocket client disconnected a session with Id {Id}");
  39. }
  40. public override void OnWsReceived(byte[] buffer, long offset, long size)
  41. {
  42. Console.WriteLine($"Incoming: {Encoding.UTF8.GetString(buffer, (int)offset, (int)size)}");
  43. }
  44. protected override void OnDisconnected()
  45. {
  46. base.OnDisconnected();
  47. Console.WriteLine($"Chat WebSocket client disconnected a session with Id {Id}");
  48. // Wait for a while...
  49. Thread.Sleep(1000);
  50. // Try to connect again
  51. if (!_stop)
  52. ConnectAsync();
  53. }
  54. protected override void OnError(SocketError error)
  55. {
  56. Console.WriteLine($"Chat WebSocket client caught an error with code {error}");
  57. }
  58. private bool _stop;
  59. }
  60. class Program
  61. {
  62. static void Main(string[] args)
  63. {
  64. // WebSocket server address
  65. string address = "127.0.0.1";
  66. if (args.Length > 0)
  67. address = args[0];
  68. // WebSocket server port
  69. int port = 8443;
  70. if (args.Length > 1)
  71. port = int.Parse(args[1]);
  72. Console.WriteLine($"WebSocket server address: {address}");
  73. Console.WriteLine($"WebSocket server port: {port}");
  74. Console.WriteLine();
  75. // Create and prepare a new SSL client context
  76. var context = new SslContext(SslProtocols.Tls12, new X509Certificate2("client.pfx", "qwerty"), (sender, certificate, chain, sslPolicyErrors) => true);
  77. // Create a new TCP chat client
  78. var client = new ChatClient(context, address, port);
  79. // Connect the client
  80. Console.Write("Client connecting...");
  81. client.ConnectAsync();
  82. Console.WriteLine("Done!");
  83. Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");
  84. // Perform text input
  85. for (;;)
  86. {
  87. string line = Console.ReadLine();
  88. if (string.IsNullOrEmpty(line))
  89. break;
  90. // Reconnect the client
  91. if (line == "!")
  92. {
  93. Console.Write("Client reconnecting...");
  94. if (client.IsConnected)
  95. client.ReconnectAsync();
  96. else
  97. client.ConnectAsync();
  98. Console.WriteLine("Done!");
  99. continue;
  100. }
  101. // Send the entered text to the chat server
  102. client.SendTextAsync(line);
  103. }
  104. // Disconnect the client
  105. Console.Write("Client disconnecting...");
  106. client.DisconnectAndStop();
  107. Console.WriteLine("Done!");
  108. }
  109. }
  110. }

Performance

Here comes several communication scenarios with timing measurements.

Benchmark environment is the following:

  1. CPU architecutre: Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz
  2. CPU logical cores: 8
  3. CPU physical cores: 4
  4. CPU clock speed: 3.998 GHz
  5. CPU Hyper-Threading: enabled
  6. RAM total: 31.962 GiB
  7. RAM free: 24.011 GiB
  8. OS version: Microsoft Windows 8 Enterprise Edition (build 9200), 64-bit
  9. OS bits: 64-bit
  10. Process bits: 64-bit
  11. Process configuaraion: release

Benchmark: Round-Trip

Round-trip

This scenario sends lots of messages from several clients to a server.
The server responses to each message and resend the similar response to
the client. The benchmark measures total round-trip time to send all
messages and receive all responses, messages & data throughput, count
of errors.

TCP echo server

  1. Server address: 127.0.0.1
  2. Server port: 1111
  3. Working clients: 1
  4. Working messages: 1000
  5. Message size: 32
  6. Seconds to benchmarking: 10
  7. Errors: 0
  8. Total time: 10.024 s
  9. Total data: 2.831 GiB
  10. Total messages: 94369133
  11. Data throughput: 287.299 MiB/s
  12. Message latency: 106 ns
  13. Message throughput: 9413997 msg/s
  1. Server address: 127.0.0.1
  2. Server port: 1111
  3. Working clients: 100
  4. Working messages: 1000
  5. Message size: 32
  6. Seconds to benchmarking: 10
  7. Errors: 0
  8. Total time: 10.189 s
  9. Total data: 1.794 GiB
  10. Total messages: 59585544
  11. Data throughput: 178.463 MiB/s
  12. Message latency: 171 ns
  13. Message throughput: 5847523 msg/s

SSL echo server

  1. Server address: 127.0.0.1
  2. Server port: 2222
  3. Working clients: 1
  4. Working messages: 1000
  5. Message size: 32
  6. Seconds to benchmarking: 10
  7. Errors: 0
  8. Total time: 2.645 s
  9. Total data: 373.329 MiB
  10. Total messages: 12233021
  11. Data throughput: 141.095 MiB/s
  12. Message latency: 216 ns
  13. Message throughput: 4623352 msg/s
  1. Server address: 127.0.0.1
  2. Server port: 2222
  3. Working clients: 100
  4. Working messages: 1000
  5. Message size: 32
  6. Seconds to benchmarking: 10
  7. Errors: 0
  8. Total time: 10.060 s
  9. Total data: 1.472 GiB
  10. Total messages: 49029133
  11. Data throughput: 148.741 MiB/s
  12. Message latency: 205 ns
  13. Message throughput: 4873398 msg/s

UDP echo server

  1. Server address: 127.0.0.1
  2. Server port: 3333
  3. Working clients: 1
  4. Working messages: 1000
  5. Message size: 32
  6. Seconds to benchmarking: 10
  7. Errors: 0
  8. Total time: 10.032 s
  9. Total data: 33.994 MiB
  10. Total messages: 1113182
  11. Data throughput: 3.395 MiB/s
  12. Message latency: 9.012 mcs
  13. Message throughput: 110960 msg/s
  1. Server address: 127.0.0.1
  2. Server port: 3333
  3. Working clients: 100
  4. Working messages: 1000
  5. Message size: 32
  6. Seconds to benchmarking: 10
  7. Errors: 0
  8. Total time: 10.635 s
  9. Total data: 20.355 MiB
  10. Total messages: 666791
  11. Data throughput: 1.934 MiB/s
  12. Message latency: 15.950 mcs
  13. Message throughput: 62693 msg/s

Unix Domain Socket echo server

  1. Server Unix Domain Socket path: C:\Users\chronoxor\AppData\Local\Temp\echo.sock
  2. Working clients: 1
  3. Working messages: 1000
  4. Message size: 32
  5. Seconds to benchmarking: 10
  6. Errors: 0
  7. Total time: 10.016 s
  8. Total data: 208.657 MiB
  9. Total messages: 6836769
  10. Data throughput: 20.850 MiB/s
  11. Message latency: 1.465 mcs
  12. Message throughput: 682575 msg/s
  1. Server Unix Domain Socket path: C:\Users\chronoxor\AppData\Local\Temp\echo.sock
  2. Working clients: 100
  3. Working messages: 1000
  4. Message size: 32
  5. Seconds to benchmarking: 10
  6. Errors: 0
  7. Total time: 12.253 s
  8. Total data: 602.320 MiB
  9. Total messages: 19736578
  10. Data throughput: 49.157 MiB/s
  11. Message latency: 620 ns
  12. Message throughput: 1610666 msg/s

Simple protocol server

  1. Server address: 127.0.0.1
  2. Server port: 4444
  3. Working clients: 1
  4. Working messages: 1000
  5. Message size: 32
  6. Seconds to benchmarking: 10
  7. Errors: 0
  8. Total time: 10.015 s
  9. Total data: 100.568 MiB
  10. Total messages: 3294993
  11. Data throughput: 10.040 MiB/s
  12. Message latency: 3.039 mcs
  13. Message throughput: 328978 msg/s
  1. Server address: 127.0.0.1
  2. Server port: 4444
  3. Working clients: 100
  4. Working messages: 1000
  5. Message size: 32
  6. Seconds to benchmarking: 10
  7. Errors: 0
  8. Total time: 12.530 s
  9. Total data: 207.994 MiB
  10. Total messages: 6814785
  11. Data throughput: 16.611 MiB/s
  12. Message latency: 1.838 mcs
  13. Message throughput: 543858 msg/s

WebSocket echo server

  1. Server address: 127.0.0.1
  2. Server port: 8080
  3. Working clients: 1
  4. Working messages: 1000
  5. Message size: 32
  6. Seconds to benchmarking: 10
  7. Errors: 0
  8. Total time: 3.037 s
  9. Total data: 105.499 MiB
  10. Total messages: 3456618
  11. Data throughput: 34.742 MiB/s
  12. Message latency: 878 ns
  13. Message throughput: 1137864 msg/s
  1. Server address: 127.0.0.1
  2. Server port: 8080
  3. Working clients: 100
  4. Working messages: 1000
  5. Message size: 32
  6. Seconds to benchmarking: 10
  7. Errors: 0
  8. Total time: 10.078 s
  9. Total data: 426.803 MiB
  10. Total messages: 13984888
  11. Data throughput: 42.353 MiB/s
  12. Message latency: 720 ns
  13. Message throughput: 1387555 msg/s

WebSocket secure echo server

  1. Server address: 127.0.0.1
  2. Server port: 8443
  3. Working clients: 1
  4. Working messages: 1000
  5. Message size: 32
  6. Seconds to benchmarking: 10
  7. Errors: 0
  8. Total time: 10.030 s
  9. Total data: 198.103 MiB
  10. Total messages: 6491390
  11. Data throughput: 19.767 MiB/s
  12. Message latency: 1.545 mcs
  13. Message throughput: 647153 msg/s
  1. Server address: 127.0.0.1
  2. Server port: 8443
  3. Working clients: 100
  4. Working messages: 1000
  5. Message size: 32
  6. Seconds to benchmarking: 10
  7. Errors: 0
  8. Total time: 10.112 s
  9. Total data: 405.286 MiB
  10. Total messages: 13280221
  11. Data throughput: 40.078 MiB/s
  12. Message latency: 761 ns
  13. Message throughput: 1313228 msg/s

Benchmark: Multicast

Multicast

In this scenario server multicasts messages to all connected clients.
The benchmark counts total messages received by all clients for all
the working time and measures messages & data throughput, count
of errors.

TCP multicast server

  1. Server address: 127.0.0.1
  2. Server port: 1111
  3. Working clients: 1
  4. Message size: 32
  5. Seconds to benchmarking: 10
  6. Errors: 0
  7. Total time: 10.022 s
  8. Total data: 407.023 MiB
  9. Total messages: 13337326
  10. Data throughput: 40.625 MiB/s
  11. Message latency: 751 ns
  12. Message throughput: 1330734 msg/s
  1. Server address: 127.0.0.1
  2. Server port: 1111
  3. Working clients: 100
  4. Message size: 32
  5. Seconds to benchmarking: 10
  6. Errors: 0
  7. Total time: 10.112 s
  8. Total data: 421.348 MiB
  9. Total messages: 13806493
  10. Data throughput: 41.681 MiB/s
  11. Message latency: 732 ns
  12. Message throughput: 1365280 msg/s

SSL multicast server

  1. Server address: 127.0.0.1
  2. Server port: 2222
  3. Working clients: 1
  4. Message size: 32
  5. Seconds to benchmarking: 10
  6. Errors: 0
  7. Total time: 10.024 s
  8. Total data: 325.225 MiB
  9. Total messages: 10656801
  10. Data throughput: 32.453 MiB/s
  11. Message latency: 940 ns
  12. Message throughput: 1063075 msg/s
  1. Server address: 127.0.0.1
  2. Server port: 2222
  3. Working clients: 100
  4. Message size: 32
  5. Seconds to benchmarking: 10
  6. Errors: 0
  7. Total time: 10.144 s
  8. Total data: 343.460 MiB
  9. Total messages: 11254173
  10. Data throughput: 33.876 MiB/s
  11. Message latency: 901 ns
  12. Message throughput: 1109393 msg/s

UDP multicast server

  1. Server address: 239.255.0.1
  2. Server port: 3333
  3. Working clients: 1
  4. Message size: 32
  5. Seconds to benchmarking: 10
  6. Errors: 0
  7. Total time: 10.026 s
  8. Total data: 13.225 MiB
  9. Total messages: 433202
  10. Data throughput: 1.326 MiB/s
  11. Message latency: 23.145 mcs
  12. Message throughput: 43205 msg/s
  1. Server address: 239.255.0.1
  2. Server port: 3333
  3. Working clients: 100
  4. Message size: 32
  5. Seconds to benchmarking: 10
  6. Errors: 0
  7. Total time: 10.035 s
  8. Total data: 28.684 MiB
  9. Total messages: 939408
  10. Data throughput: 2.877 MiB/s
  11. Message latency: 10.682 mcs
  12. Message throughput: 93606 msg/s

Unix Domain Socket multicast server

  1. Server Unix Domain Socket path: C:\Users\chronoxor\AppData\Local\Temp\multicast.sock
  2. Working clients: 1
  3. Message size: 32
  4. Seconds to benchmarking: 10
  5. Errors: 0
  6. Total time: 10.015 s
  7. Total data: 204.127 MiB
  8. Total messages: 6688763
  9. Data throughput: 20.390 MiB/s
  10. Message latency: 1.497 mcs
  11. Message throughput: 667869 msg/s
  1. Server Unix Domain Socket path: C:\Users\chronoxor\AppData\Local\Temp\multicast.sock
  2. Working clients: 100
  3. Message size: 32
  4. Seconds to benchmarking: 10
  5. Errors: 0
  6. Total time: 10.033 s
  7. Total data: 124.463 MiB
  8. Total messages: 4078051
  9. Data throughput: 12.413 MiB/s
  10. Message latency: 2.460 mcs
  11. Message throughput: 406451 msg/s

WebSocket multicast server

  1. Server address: 127.0.0.1
  2. Server port: 8080
  3. Working clients: 1
  4. Message size: 32
  5. Seconds to benchmarking: 10
  6. Errors: 0
  7. Total time: 10.048 s
  8. Total data: 183.108 MiB
  9. Total messages: 6000000
  10. Data throughput: 18.228 MiB/s
  11. Message latency: 1.674 mcs
  12. Message throughput: 597121 msg/s
  1. Server address: 127.0.0.1
  2. Server port: 8080
  3. Working clients: 100
  4. Message size: 32
  5. Seconds to benchmarking: 10
  6. Errors: 0
  7. Total time: 10.227 s
  8. Total data: 125.957 MiB
  9. Total messages: 4126627
  10. Data throughput: 12.320 MiB/s
  11. Message latency: 2.478 mcs
  12. Message throughput: 403466 msg/s

WebSocket secure multicast server

  1. Server address: 127.0.0.1
  2. Server port: 8443
  3. Working clients: 1
  4. Message size: 32
  5. Seconds to benchmarking: 10
  6. Errors: 0
  7. Total time: 10.034 s
  8. Total data: 184.159 MiB
  9. Total messages: 6034421
  10. Data throughput: 18.359 MiB/s
  11. Message latency: 1.662 mcs
  12. Message throughput: 601338 msg/s
  1. Server address: 127.0.0.1
  2. Server port: 8443
  3. Working clients: 100
  4. Message size: 32
  5. Seconds to benchmarking: 10
  6. Errors: 0
  7. Total time: 10.171 s
  8. Total data: 315.306 MiB
  9. Total messages: 10331721
  10. Data throughput: 30.1022 MiB/s
  11. Message latency: 984 ns
  12. Message throughput: 1015763 msg/s

Benchmark: Web Server

HTTP Trace server

  1. Server address: 127.0.0.1
  2. Server port: 8080
  3. Working clients: 1
  4. Working messages: 1
  5. Seconds to benchmarking: 10
  6. Errors: 0
  7. Total time: 10.023 s
  8. Total data: 10.987 MiB
  9. Total messages: 108465
  10. Data throughput: 1.096 MiB/s
  11. Message latency: 92.414 mcs
  12. Message throughput: 10820 msg/s
  1. Server address: 127.0.0.1
  2. Server port: 8080
  3. Working clients: 100
  4. Working messages: 1
  5. Seconds to benchmarking: 10
  6. Errors: 0
  7. Total time: 10.085 s
  8. Total data: 40.382 MiB
  9. Total messages: 401472
  10. Data throughput: 4.003 MiB/s
  11. Message latency: 25.120 mcs
  12. Message throughput: 39807 msg/s

HTTPS Trace server

  1. Server address: 127.0.0.1
  2. Server port: 8443
  3. Working clients: 1
  4. Working messages: 1
  5. Seconds to benchmarking: 10
  6. Errors: 0
  7. Total time: 595.214 ms
  8. Total data: 627.842 KiB
  9. Total messages: 6065
  10. Data throughput: 1.030 MiB/s
  11. Message latency: 98.139 mcs
  12. Message throughput: 10189 msg/s
  1. Server address: 127.0.0.1
  2. Server port: 8443
  3. Working clients: 100
  4. Working messages: 1
  5. Seconds to benchmarking: 10
  6. Errors: 0
  7. Total time: 3.548 s
  8. Total data: 17.948 MiB
  9. Total messages: 179111
  10. Data throughput: 5.052 MiB/s
  11. Message latency: 19.813 mcs
  12. Message throughput: 50471 msg/s

OpenSSL certificates

In order to create OpenSSL based server and client you should prepare a set of
SSL certificates.

Production

Depending on your project, you may need to purchase a traditional SSL
certificate signed by a Certificate Authority. If you, for instance,
want some else’s web browser to talk to your WebSocket project, you’ll
need a traditional SSL certificate.

Development

The commands below entered in the order they are listed will generate a
self-signed certificate for development or testing purposes.

Certificate Authority

  • Create CA private key

    1. openssl genrsa -passout pass:qwerty -out ca-secret.key 4096
  • Remove passphrase

    1. openssl rsa -passin pass:qwerty -in ca-secret.key -out ca.key
  • Create CA self-signed certificate

    1. 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

    1. openssl pkcs12 -export -passout pass:qwerty -inkey ca.key -in ca.crt -out ca.pfx
  • Convert CA self-signed certificate to PEM

    1. openssl pkcs12 -passin pass:qwerty -passout pass:qwerty -in ca.pfx -out ca.pem

SSL Server certificate

  • Create private key for the server

    1. openssl genrsa -passout pass:qwerty -out server-secret.key 4096
  • Remove passphrase

    1. openssl rsa -passin pass:qwerty -in server-secret.key -out server.key
  • Create CSR for the server

    1. 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

    1. 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

    1. openssl pkcs12 -export -passout pass:qwerty -inkey server.key -in server.crt -out server.pfx
  • Convert the server certificate to PEM

    1. openssl pkcs12 -passin pass:qwerty -passout pass:qwerty -in server.pfx -out server.pem

SSL Client certificate

  • Create private key for the client

    1. openssl genrsa -passout pass:qwerty -out client-secret.key 4096
  • Remove passphrase

    1. openssl rsa -passin pass:qwerty -in client-secret.key -out client.key
  • Create CSR for the client

    1. 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

    1. 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

    1. openssl pkcs12 -export -passout pass:qwerty -inkey client.key -in client.crt -out client.pfx
  • Convert the client certificate to PEM

    1. openssl pkcs12 -passin pass:qwerty -passout pass:qwerty -in client.pfx -out client.pem

Diffie-Hellman key exchange

  • Create DH parameters
    1. openssl dhparam -out dh4096.pem 4096