EonaCat.Connections 1.1.2

Prefix Reserved
dotnet add package EonaCat.Connections --version 1.1.2
                    
NuGet\Install-Package EonaCat.Connections -Version 1.1.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EonaCat.Connections" Version="1.1.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EonaCat.Connections" Version="1.1.2" />
                    
Directory.Packages.props
<PackageReference Include="EonaCat.Connections" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EonaCat.Connections --version 1.1.2
                    
#r "nuget: EonaCat.Connections, 1.1.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package EonaCat.Connections@1.1.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EonaCat.Connections&version=1.1.2
                    
Install as a Cake Addin
#tool nuget:?package=EonaCat.Connections&version=1.1.2
                    
Install as a Cake Tool

EonaCat.Connections

A high-performance, production-ready .netStandard 2.0, .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)
  • DisconnectOnMissedPong: 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.DisconnectOnMissedPong = 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 Standard 2.0** - Full support
  • .NET Framework 4.8+ - Full support
  • .NET 8.0 - Full support
  • Platforms: Windows, Linux, macOS (with .NET Core)
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 is compatible.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.2 138 6/17/2026
1.1.1 117 6/17/2026
1.1.0 130 6/17/2026
1.0.9 174 11/28/2025
1.0.8 228 9/24/2025
1.0.7 273 8/27/2025