Files
EonaCat.Connections/README.md
T
2026-06-17 08:20:52 +02:00

30 KiB

EonaCat.Connections

A high-performance, production-ready .NET Framework 4.8+ / .NET 8 compatible library for building scalable TCP/UDP servers and clients with optional TLS encryption and application-layer AES encryption.

Features

Core Capabilities

  • High Performance: Event-driven, asynchronous architecture with minimal allocations
  • Massive Scalability: Handles tens of thousands of concurrent connections using SocketAsyncEventArgs (SAEA)
  • Dual Protocol Support: TCP and UDP with independent or mixed configurations
  • TLS/SSL Encryption: Secure TCP connections using SslStream with certificate support
  • Application-Layer Encryption: AES-CBC + PBKDF2_SHA256 encryption for both TCP and UDP payloads
  • Low Latency: Optimized for millisecond-level response times

Advanced Features

  • Auto-Reconnection: Automatic client reconnection with configurable retry logic and exponential backoff
  • Heartbeat/Ping-Pong: Keep-alive mechanism to detect dead connections
  • Idle Detection: Automatic detection and handling of idle connections with configurable timeout
  • Message Framing: Support for delimiter-based, length-prefixed, or raw message modes
  • Request-Response Patterns: Send message and wait for response with timeout support
  • Broadcast Messaging: Send to all connected clients simultaneously
  • Client-to-Client Messaging: Direct peer communication through the server
  • Nicknames: Optional client identification system
  • Health API: Lightweight REST API for monitoring server health and statistics
  • Status Reporting: Auto-generated HTML status pages showing connected clients and throughput
  • Network Monitoring: Built-in network health monitoring and outage detection
  • SSL Diagnostics: Detailed SSL handshake diagnostics and performance metrics
  • Connection Management: Full lifecycle management with detailed disconnect reasons

Design Goals

  • High performance and low latency
  • Scalable to tens of thousands of concurrent connections
  • Scalable socket I/O via SocketAsyncEventArgs (SAEA) for raw TCP and UDP
  • TLS (SSL) over TCP using SslStream (built-in)
  • Optional encryption (AES-CBC + PBKDF2_SHA256) for TCP/UDP payloads
  • Minimal allocations, event-driven callbacks
  • For highest throughput, run x64, enable LargePage, set appropriate Socket options and OS registry tuning

Configuration

The Configuration class provides extensive customization options:

Connection Settings

  • Protocol: TCP or UDP (default: TCP)
  • Host: Server address for clients (default: 127.0.0.1)
  • Port: Network port (default: 8080)
  • MaxConnections: Maximum concurrent connections (default: 100000)
  • ConnectionTimeout: Timeout for connection attempts (default: 30s)

TLS/SSL Settings

  • Certificate: X509Certificate2 for server (enables TLS when set)
  • AdditionalCertificates: Additional certificates for chain validation
  • IsSelfSignedEnabled: Allow self-signed certificates (testing only)
  • CheckCertificateRevocation: Validate certificate revocation status
  • MutuallyAuthenticate: Require mutual TLS authentication
  • UseSsl: Read-only property (true if Certificate is set)
  • EnableSslDiagnostics: Enable detailed SSL handshake diagnostics
  • AllowTlsRenegotiation: Allow TLS renegotiation

SSL Retry & Handshake Configuration

  • SSLMaxRetries: Maximum SSL handshake retry attempts (0 = unlimited, default: 0)
  • SSLTimeoutInSeconds: SSL handshake timeout (default: 35)
  • SSLRetryDelayInSeconds: Delay between SSL retries (default: 5)
  • UseExponentialBackoffForSslRetries: Enable exponential backoff (default: false)
  • SSLRetryDelayMaxSeconds: Maximum retry delay when exponential backoff enabled (default: 60)

Encryption Settings

  • UseAesEncryption: Enable AES-CBC encryption (default: false)
  • AesPassword: Password for AES key derivation
  • UseBigEndian: Use big-endian byte order (default: false)

Keep-Alive & Heartbeat

  • EnableKeepAlive: Enable TCP keep-alive probes (default: true)
  • KeepAliveTimeSeconds: Time before first keep-alive probe (default: 60)
  • KeepAliveIntervalSeconds: Interval between probes (default: 10)
  • KeepAliveRetryCount: Unacked probes before disconnect (default: 10)
  • EnableHeartbeat: Enable ping-pong heartbeat (default: false)
  • HeartbeatIntervalSeconds: Heartbeat interval (default: 5)
  • EnablePingPongLogs: Log ping-pong messages (default: false)
  • DisconectOnMissedPong: Disconnect on missed pong response (default: false)

Message Framing

  • MessageFraming: None, Delimiter, or LengthPrefixed (default: None)
  • Delimiter: Message separator bytes (default: %)
  • LengthPrefixedLength: Prefix byte count for length-prefixed mode (default: 4)
  • MAX_MESSAGE_SIZE: Maximum message size (default: 100 MB)

Idle Detection & Timeout

  • IdleTimeoutSeconds: Idle connection timeout, 0 = disabled (default: 30)

Socket Configuration

  • BufferSize: Socket buffer size (default: ExtraLarge ~65K)
  • EnableNagle: Enable Nagle's algorithm (default: false)
  • EnableRST: Send RST flag on close (default: false)

Auto-Reconnection (Client)

  • EnableAutoReconnect: Auto-reconnect on disconnect (default: true)
  • ReconnectDelayInSeconds: Delay before reconnection attempt (default: 5)
  • MaxReconnectAttempts: Max reconnect attempts, 0 = unlimited (default: 0)

Logging & Diagnostics

  • EnableConnectionDebugLogs: Log connection lifecycle events (default: false)

HTML Status & Health API

  • EnableAutoHtmlReports: Generate periodic HTML error reports (default: false)
  • HtmlReportOutputDirectory: Report output directory (default: ./reports)
  • HtmlReportIntervalSeconds: Report generation interval (default: 60)
  • EnableServerStatusPage: Generate HTML status page with client list (default: false)
  • ServerStatusPageIntervalSeconds: Status page update interval (default: 5)
  • EnableHealthApi: Start lightweight REST health API (default: false)
  • HealthApiPort: Health API port, 0 = random (default: 0)
  • HealthApiBindAddress: Health API bind address (default: 127.0.0.1)

Certificate Management

  • TrustedThumbprints: List of trusted certificate thumbprints for validation
  • CheckAgainstInternalTrustedCertificates: Validate against Windows certificate store (default: true)

NetworkServer API

Events

// Connection events
public event EventHandler<ConnectionEventArgs> OnConnected;
public event EventHandler<ConnectionEventArgs> OnConnectedWithNickname;
public event EventHandler<ConnectionEventArgs> OnDisconnected;

// Data events
public event EventHandler<DataReceivedEventArgs> OnDataReceived;

// Error events
public event EventHandler<ErrorEventArgs> OnSslError;
public event EventHandler<ErrorEventArgs> OnEncryptionError;
public event EventHandler<ErrorEventArgs> OnGeneralError;
public event EventHandler<ErrorEventArgs> OnSocketError;

// Heartbeat events
public event EventHandler<PingEventArgs> OnClientPingResponse;
public event EventHandler<PingEventArgs> OnPongMissed;

// Idle/Timeout events
public event EventHandler<IdleEventArgs> OnIdleTimeout;

// Logging
public event EventHandler<string> OnLog;

Properties

// Server Status
public bool IsStarted { get; }
public int Port { get; }
public int ActiveConnections { get; }
public int MaxConnections { get; }
public ProtocolType Protocol { get; }

// Security Status
public bool IsSecure { get; }              // TLS or AES enabled
public bool IsEncrypted { get; }           // AES enabled

// Statistics
public long DroppedPackets { get; }
public long DroppedConnections { get; }
public long TotalConnections { get; }
public long BytesSent { get; }
public long BytesReceived { get; }
public long MessagesSent { get; }
public long MessagesReceived { get; }
public double MessagesPerSecond { get; }
public TimeSpan Uptime { get; }
public DateTime StartTime { get; }
public DateTime LastDataSent { get; }
public DateTime LastDataReceived { get; }

// Status Pages
public ServerStatusPage ServerStatus { get; }
public SocketStatusPage StatusPage { get; }
public HealthApiServer HealthApi { get; }

// Debug
public bool DEBUG_DATA_SEND { get; set; }
public bool DEBUG_DATA_RECEIVED { get; set; }

Core Methods

// Lifecycle
public Task StartAsync();
public void Stop();
public async Task StopAsync();
public Task StartTcpServerAsync();
public async Task StartUdpServerAsync(CancellationToken token);
public async Task StopTcpServerAsync();

// Client Management
public Dictionary<string, Connection> GetClients();
public List<Connection> GetClient(string clientId);
public async Task DisconnectClientAsync(string clientId, DisconnectReason reason, Exception? exception);

// Messaging - Send to Specific Client
public async Task<bool> SendToClientAsync(string clientId, byte[] data);
public async Task<bool> SendToClientAsync(string clientId, string message);

// Messaging - Client-to-Client
public async Task<bool> SendFromClientToClientAsync(string fromClientId, string toClientId, byte[] data);
public async Task<bool> SendFromClientToClientAsync(string fromClientId, string toClientId, string message);

// Broadcast Messaging
public async Task<bool> BroadcastAsync(byte[] data);
public async Task<bool> BroadcastAsync(string message);

// Request-Response Patterns
public async Task<DataReceivedEventArgs> SendToClientAndWaitForResponseAsync(
	string clientId, byte[] data, TimeSpan? timeout = null);
public async Task<DataReceivedEventArgs> SendToClientAndWaitForResponseAsync(
	string clientId, string message, TimeSpan? timeout = null);

public async Task<DataReceivedEventArgs> SendFromClientToClientAndWaitForResponseAsync(
	string fromClientId, string toClientId, byte[] data, TimeSpan? timeout = null);
public async Task<DataReceivedEventArgs> SendFromClientToClientAndWaitForResponseAsync(
	string fromClientId, string toClientId, string message, TimeSpan? timeout = null);

public async Task<List<DataReceivedEventArgs>> BroadcastAndWaitForResponsesAsync(
	byte[] data, TimeSpan? timeout = null);
public async Task<List<DataReceivedEventArgs>> BroadcastAndWaitForResponsesAsync(
	string message, TimeSpan? timeout = null);

// Configuration
public void SetSeparator(string separator);
public void SetSeparator(byte[] separator);

// Statistics
public Stats GetStats();

// Cleanup
public void Dispose();

NetworkClient API

Events

// Connection events
public event EventHandler<ConnectionEventArgs> OnConnected;
public event EventHandler<ConnectionEventArgs> OnNicknameSend;
public event EventHandler<ConnectionEventArgs> OnDisconnected;

// Data events
public event EventHandler<DataReceivedEventArgs> OnDataReceived;

// Error events
public event EventHandler<ErrorEventArgs> OnSslError;
public event EventHandler<ErrorEventArgs> OnEncryptionError;
public event EventHandler<ErrorEventArgs> OnGeneralError;
public event EventHandler<ErrorEventArgs> OnSocketError;

// Heartbeat events
public event EventHandler<PingEventArgs> OnPingResponse;
public event EventHandler<PingEventArgs> OnPongResponse;

// Idle/Timeout events
public event EventHandler<IdleClientEventArgs> OnIdleTimeout;

// Logging
public event EventHandler<string> OnLog;

Properties

// Connection Status
public bool IsConnected { get; set; }
public int Port { get; }

// Connection Time Metrics
public DateTime ConnectionTime { get; }
public TimeSpan Uptime { get; }
public DateTime LastActive { get; }
public int IdleTimeInSeconds();
public int IdleTimeInMinutes();
public int IdleTimeInHours();
public int IdleTimeInDays();
public int ConnectedTimeInSeconds();
public int ConnectedTimeInMinutes();
public int ConnectedTimeInHours();
public int ConnectedTimeInDays();

// Security Status
public bool IsSecure { get; }              // TLS or AES enabled
public bool IsEncrypted { get; }           // AES enabled
public bool IsTcp { get; }

// Statistics
public long BytesSent { get; }
public long BytesReceived { get; }
public long MessagesSent { get; }
public long MessagesReceived { get; }

// Heartbeat
public bool DisconnectOnMissedPong { get; set; }
public bool EnableKeepAlive { get; set; }

// Auto-Reconnect
public bool IsAutoConnectStarted { get; }
public bool IsIdleTimeoutTriggered { get; }

// Debug
public bool DEBUG_DATA_SEND { get; set; }
public bool DEBUG_DATA_RECEIVED { get; set; }

Core Methods

// Connection Lifecycle
public async Task<bool> ConnectAsync();
public async Task DisconnectAsync();
public async Task DisconnectDueTimeoutAsync();

// Messaging
public async Task<bool> SendAsync(byte[] data);
public async Task<bool> SendAsync(string message);

// Nickname
public async Task<bool> SendNicknameAsync(string nickname);

// Request-Response
public async Task<DataReceivedEventArgs> SendAndWaitForResponseAsync(
	byte[] data, TimeSpan? timeout = null);
public async Task<DataReceivedEventArgs> SendAndWaitForResponseAsync(
	string message, TimeSpan? timeout = null);
public async Task<DataReceivedEventArgs> SendNicknameAndWaitForResponseAsync(
	string nickname, TimeSpan? timeout = null);

// Cleanup
public void Dispose();

Message Framing Modes

Three message framing modes are supported:

1. None (Default)

Raw bytes sent as-is, no frame boundaries marked:

config.MessageFraming = FramingMode.None;

2. Delimiter

Messages separated by a delimiter byte sequence (default: %):

config.MessageFraming = FramingMode.Delimiter;
config.Delimiter = Encoding.UTF8.GetBytes("%");

3. Length-Prefixed

Messages prefixed with their length as bytes:

config.MessageFraming = FramingMode.LengthPrefixed;
config.LengthPrefixedLength = 4;  // 4-byte prefix

SSL/TLS Certificate Setup

Generate self-signed certificate for TLS (TCP):

Run the following in PowerShell as Administrator:

$cert = New-SelfSignedCertificate `
	-DnsName "localhost" `
	-CertStoreLocation "Cert:\LocalMachine\My" `
	-KeyExportPolicy Exportable `
	-NotAfter (Get-Date).AddYears(5) `
	-FriendlyName "EonaCat Connections Test Certificate"

$password = ConvertTo-SecureString -String "p@ss" -Force -AsPlainText

Export-PfxCertificate `
	-Cert "Cert:\LocalMachine\My\$($cert.Thumbprint)" `
	-FilePath "C:\temp\server.pfx" `
	-Password $password

This creates a self-signed certificate with password p@ss in C:\temp\server.pfx.


Advanced Features

Auto-Reconnection

The client automatically reconnects on disconnect:

config.EnableAutoReconnect = true;      // Enable auto-reconnect
config.ReconnectDelayInSeconds = 5;     // Delay before retry
config.MaxReconnectAttempts = 0;        // 0 = unlimited attempts

Heartbeat (Ping-Pong)

Keep connections alive and detect dead connections:

config.EnableHeartbeat = true;
config.HeartbeatIntervalSeconds = 5;
config.DisconectOnMissedPong = true;    // Disconnect if pong not received

Idle Detection

Automatically disconnect idle connections:

config.IdleTimeoutSeconds = 30;         // 0 = disabled

Request-Response Patterns

Send a message and wait for a response with timeout:

// Server sends message and waits for client response
var response = await server.SendToClientAndWaitForResponseAsync(
	clientId, "question", TimeSpan.FromSeconds(5));

if (response != null)
{
	Console.WriteLine($"Got response: {response.StringData}");
}

// Client sends message and waits for server response
var response = await client.SendAndWaitForResponseAsync(
	"answer", TimeSpan.FromSeconds(5));

Health API

Enable a lightweight REST API for server monitoring:

config.EnableHealthApi = true;
config.HealthApiPort = 0;  // Random port
config.HealthApiBindAddress = IPAddress.Any;  // For Docker/containers

// After server starts, access the API:
// http://localhost:{HealthApi.Port}/health
// http://localhost:{HealthApi.Port}/stats

Status Pages

Auto-generate HTML status reports:

config.EnableServerStatusPage = true;
config.ServerStatusPageIntervalSeconds = 5;

config.EnableAutoHtmlReports = true;
config.HtmlReportOutputDirectory = "./reports";
config.HtmlReportIntervalSeconds = 60;

SSL Diagnostics

Enable detailed SSL handshake diagnostics:

config.EnableSslDiagnostics = true;
// Access via: server.StatusPage.SslMetrics

Network Monitoring

Monitor network health and detect outages:

var monitor = new NetworkMonitor();
monitor.OnNetworkOutageDetected += (s, e) => 
{
	Console.WriteLine($"Network outage detected: {e.Duration}");
};

Server Example

using EonaCat.Connections;
using EonaCat.Connections.Models;
using System.Security.Cryptography.X509Certificates;

namespace EonaCat.Connections.Server.Example
{
	public class Program
	{
		private static NetworkServer _server;

		public static void Main(string[] args)
		{
			CreateServerAsync().GetAwaiter().GetResult();

			while (true)
			{
				Console.Write("Enter message to broadcast (or 'exit' to quit): ");
				var message = Console.ReadLine();

				if (!string.IsNullOrEmpty(message) && message.Equals("exit", StringComparison.OrdinalIgnoreCase))
				{
					_server.StopAsync().GetAwaiter().GetResult();
					_server.Dispose();
					Console.WriteLine("Server stopped.");
					break;
				}

				if (!string.IsNullOrEmpty(message))
				{
					_server.BroadcastAsync(message).GetAwaiter().GetResult();
				}
			}
		}

		private static async Task CreateServerAsync()
		{
			var config = new Configuration
			{
				Protocol = ProtocolType.TCP,
				Port = 1111,
				Certificate = new X509Certificate2("server.pfx", "p@ss"),  // Enables TLS
				UseAesEncryption = true,
				AesPassword = "EonaCat.Connections.Password",
				MaxConnections = 100000,
				EnableHeartbeat = true,
				HeartbeatIntervalSeconds = 5,
				IdleTimeoutSeconds = 30,
				EnableHealthApi = true,
				HealthApiPort = 8888,
			};

			_server = new NetworkServer(config);

			// Connection events
			_server.OnConnected += (sender, e) =>
				Console.WriteLine($"[CONNECTED] Client {e.ClientId} from {e.RemoteEndPoint}");

			_server.OnConnectedWithNickname += (sender, e) =>
				Console.WriteLine($"[NICKNAME] Client {e.ClientId} identified as: {e.Nickname}");

			// Data reception
			_server.OnDataReceived += async (sender, e) =>
			{
				var clientName = e.HasNickname ? e.Nickname : e.ClientId;
				Console.WriteLine($"[DATA] From {clientName}: {(e.IsBinary ? $"{e.Data.Length} bytes" : e.StringData)}");

				// Echo response
				if (e.IsBinary)
				{
					await _server.SendToClientAsync(e.ClientId, e.Data);
				}
				else
				{
					await _server.SendToClientAsync(e.ClientId, $"Echo: {e.StringData}");
				}
			};

			// Disconnection
			_server.OnDisconnected += (sender, e) =>
			{
				var clientName = e.HasNickname ? e.Nickname : e.ClientId;
				Console.WriteLine($"[DISCONNECTED] {clientName} ({e.DisconnectReason})");
			};

			// Error handling
			_server.OnGeneralError += (sender, e) =>
				Console.WriteLine($"[ERROR] {e.Message}");

			_server.OnSslError += (sender, e) =>
				Console.WriteLine($"[SSL ERROR] {e.Message}");

			// Idle connections
			_server.OnIdleTimeout += (sender, e) =>
				Console.WriteLine($"[IDLE] Client disconnected due to timeout: {e.ClientId}");

			// Heartbeat
			_server.OnPongMissed += (sender, e) =>
				Console.WriteLine($"[HEARTBEAT] Pong missed from {e.ClientId}");

			Console.WriteLine("Server starting...");
			await _server.StartAsync();
			Console.WriteLine($"Server listening on port {_server.Port}");
			Console.WriteLine($"Health API available on: http://localhost:8888/health");
		}
	}
}

Client Example

using EonaCat.Connections;
using EonaCat.Connections.Models;
using System.Security.Cryptography.X509Certificates;

namespace EonaCat.Connections.Client.Example
{
	public class Program
	{
		private static NetworkClient _client;

		public static async Task Main(string[] args)
		{
			await CreateClientAsync();

			while (true)
			{
				if (!_client.IsConnected)
				{
					Console.WriteLine("Waiting for connection...");
					await Task.Delay(1000);
					continue;
				}

				Console.Write("Enter message to send (or 'exit' to quit): ");
				var message = Console.ReadLine();

				if (!string.IsNullOrEmpty(message) && message.Equals("exit", StringComparison.OrdinalIgnoreCase))
				{
					await _client.DisconnectAsync();
					_client.Dispose();
					break;
				}

				if (!string.IsNullOrEmpty(message))
				{
					await _client.SendAsync(message);

					// Optional: wait for response
					var response = await _client.SendAndWaitForResponseAsync(
						message, TimeSpan.FromSeconds(5));

					if (response != null)
					{
						Console.WriteLine($"Server response: {response.StringData}");
					}
				}
			}
		}

		private static async Task CreateClientAsync()
		{
			var config = new Configuration
			{
				Protocol = ProtocolType.TCP,
				Host = "127.0.0.1",
				Port = 1111,
				Certificate = new X509Certificate2("client.pfx", "p@ss"),  // For TLS (optional)
				UseAesEncryption = true,
				AesPassword = "EonaCat.Connections.Password",
				EnableAutoReconnect = true,
				ReconnectDelayInSeconds = 5,
				MaxReconnectAttempts = 0,  // Unlimited retries
				EnableHeartbeat = true,
				HeartbeatIntervalSeconds = 5,
				IdleTimeoutSeconds = 30,
			};

			_client = new NetworkClient(config);

			// Error handling
			_client.OnGeneralError += (sender, e) =>
				Console.WriteLine($"[ERROR] {e.Message}");

			_client.OnSslError += (sender, e) =>
				Console.WriteLine($"[SSL ERROR] {e.Message}");

			// Connection events
			_client.OnConnected += async (sender, e) =>
			{
				Console.WriteLine($"[CONNECTED] Connected to server at {e.RemoteEndPoint}");

				// Set client nickname
				await _client.SendNicknameAsync("TestUser");

				// Send initial message
				await _client.SendAsync("Hello from client!");
			};

			// Data reception
			_client.OnDataReceived += (sender, e) =>
				Console.WriteLine($"[SERVER] {(e.IsBinary ? $"{e.Data.Length} bytes" : e.StringData)}");

			// Disconnection
			_client.OnDisconnected += (sender, e) =>
				Console.WriteLine($"[DISCONNECTED] Disconnected from server ({e.DisconnectReason})");

			// Idle/Timeout
			_client.OnIdleTimeout += (sender, e) =>
				Console.WriteLine($"[IDLE] Connection idle for {e.IdleTime} seconds");

			// Heartbeat
			_client.OnPingResponse += (sender, e) =>
				Console.WriteLine($"[PING] Response time: {e.ResponseTime}ms");

			Console.WriteLine("Client connecting...");
			await _client.ConnectAsync();
		}
	}
}

Advanced Usage Examples

Request-Response Pattern

// Server: Wait for client to send data, then respond
_server.OnDataReceived += async (sender, e) =>
{
	if (e.StringData == "QUERY")
	{
		await _server.SendToClientAsync(e.ClientId, "RESPONSE_DATA");
	}
};

// Client: Send request and wait for response
var response = await _client.SendAndWaitForResponseAsync(
	"QUERY", TimeSpan.FromSeconds(10));
Console.WriteLine($"Got: {response.StringData}");

// Server: Broadcast and wait for all responses
var responses = await _server.BroadcastAndWaitForResponsesAsync(
	"QUESTION", TimeSpan.FromSeconds(15));
Console.WriteLine($"Received {responses.Count} responses");

Client-to-Client Communication

// Client A sends to Client B through server
await _server.SendFromClientToClientAsync(
	"clientA_id", "clientB_id", "Direct message");

// Or with response
var response = await _server.SendFromClientToClientAndWaitForResponseAsync(
	"clientA_id", "clientB_id", "Question for B");

Message Framing

// Delimiter-based framing
config.MessageFraming = FramingMode.Delimiter;
config.Delimiter = Encoding.UTF8.GetBytes("\n");

// Length-prefixed framing
config.MessageFraming = FramingMode.LengthPrefixed;
config.LengthPrefixedLength = 4;  // 4-byte length prefix

// Custom separator
server.SetSeparator("||");

Accessing Statistics

// Server statistics
Console.WriteLine($"Active connections: {_server.ActiveConnections}");
Console.WriteLine($"Total connected: {_server.TotalConnections}");
Console.WriteLine($"Messages/sec: {_server.MessagesPerSecond}");
Console.WriteLine($"Data sent: {_server.BytesSent} bytes");
Console.WriteLine($"Data received: {_server.BytesReceived} bytes");
Console.WriteLine($"Uptime: {_server.Uptime}");

var stats = _server.GetStats();
Console.WriteLine($"Dropped packets: {stats.DroppedPackets}");
Console.WriteLine($"Dropped connections: {stats.DroppedConnections}");

// Client statistics
Console.WriteLine($"Connection time: {_client.ConnectedTimeInHours()} hours");
Console.WriteLine($"Idle time: {_client.IdleTimeInSeconds()} seconds");
Console.WriteLine($"Bytes sent: {_client.BytesSent}");
Console.WriteLine($"Messages sent: {_client.MessagesSent}");

SSL/TLS with Certificate Validation

// Server with certificate
var config = new Configuration
{
	Certificate = new X509Certificate2("server.pfx", "password"),
	MutuallyAuthenticate = true,
	CheckCertificateRevocation = true,
};

// Client with certificate validation
var clientConfig = new Configuration
{
	Host = "server.example.com",
	Port = 443,
	Certificate = new X509Certificate2("client.pfx", "password"),
	MutuallyAuthenticate = true,
	TrustedThumbprints = new List<string> { "CERT_THUMBPRINT" },
	CheckCertificateRevocation = true,
};

Encryption and Security

// AES Encryption
config.UseAesEncryption = true;
config.AesPassword = "SecurePassword123";

// Both TLS and AES together
config.Certificate = new X509Certificate2("server.pfx", "pass");
config.UseAesEncryption = true;
config.AesPassword = "AdditionalPassword";

// Disable Nagle for low-latency
config.EnableNagle = false;

Event Arguments Reference

ConnectionEventArgs

  • string ClientId - Unique client identifier
  • EndPoint RemoteEndPoint - Client's remote address/port
  • string Nickname - Client's nickname (if set)
  • bool HasNickname - Whether client has a nickname

DataReceivedEventArgs

  • string ClientId - Sender client ID
  • byte[] Data - Raw binary data
  • string StringData - Data decoded as UTF-8 string
  • bool IsBinary - True if binary data, false if text
  • bool HasNickname - Whether sender has a nickname
  • string Nickname - Sender's nickname (if set)

ErrorEventArgs

  • string Message - Error description
  • string ClientId - Associated client (if applicable)
  • Exception Exception - Inner exception details

PingEventArgs

  • string ClientId - Client that responded to ping
  • long ResponseTime - Response time in milliseconds

IdleEventArgs / IdleClientEventArgs

  • string ClientId - Idle client ID
  • double IdleTime - Idle duration in seconds
  • DisconnectReason Reason - Reason for disconnection

Disconnect Reasons

The DisconnectReason enum provides detailed disconnect information:

public enum DisconnectReason
{
	Unknown,              // Unknown reason
	RemoteClosed,        // Remote peer closed connection
	LocalClosed,         // Local side closed connection
	Timeout,             // Connection timeout
	Error,               // General error
	SSLError,            // SSL/TLS handshake error
	ServerShutdown,      // Server shutting down
	Reconnect,           // Reconnecting (client)
	ClientRequested,     // Client requested disconnect
	Forced,              // Forcefully disconnected
	NoPongReceived,      // Heartbeat pong not received
	ProtocolError,       // Protocol violation
}

Performance Considerations

Optimization Tips

  1. Disable Nagle's Algorithm: Set EnableNagle = false for lower latency
  2. Buffer Size: Use appropriate BufferSize (default is ExtraLarge ~65KB)
  3. Keep-Alive: Enable EnableKeepAlive to detect dead connections early
  4. Message Framing: Use LengthPrefixed for better parsing performance
  5. Connection Pool: Design clients to maintain persistent connections
  6. Batching: Group small messages when possible
  7. Thread Affinity: Run on dedicated cores for high throughput

Monitoring

  • Use HealthApi for external monitoring
  • Enable EnableServerStatusPage for HTML reports
  • Monitor MessagesPerSecond for throughput
  • Track IdleTimeout events for connection health
  • Use NetworkMonitor for advanced diagnostics

Thread Safety

  • NetworkServer and NetworkClient are thread-safe for all public methods
  • Events are called on socket completion threads
  • Use ConfigureAwait(false) in async handlers
  • Access shared state with appropriate synchronization

Supported Platforms

  • .NET Framework 4.8+ - Full support
  • .NET 8.0 - Full support
  • Platforms: Windows, Linux, macOS (with .NET Core)

License

Licensed under the Apache License. See LICENSE file for details.


Resources