Impleemnting a Multi-Client TCP Server
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
public class NetworkServer
{
private readonly TcpListener _tcpListener;
private readonly int _listeningPort;
public NetworkServer(int port)
{
_listeningPort = port;
_tcpListener = new TcpListener(IPAddress.Any, port);
}
public async Task BeginListeningAsync()
{
_tcpListener.Start();
Console.WriteLine($"Server started on port {_listeningPort}");
while (true)
{
var incomingConnection = await _tcpListener.AcceptTcpClientAsync();
_ = ProcessConnectionAsync(incomingConnection);
}
}
private async Task ProcessConnectionAsync(TcpClient connection)
{
try
{
var endpoint = connection.Client.RemoteEndPoint;
Console.WriteLine($"New client connected from {endpoint}");
using (connection)
using (var dataStream = connection.GetStream())
{
var receiveBuffer = new byte[4096];
int dataReceived;
while ((dataReceived = await dataStream.ReadAsync(receiveBuffer, 0, receiveBuffer.Length)) > 0)
{
var receivedText = Encoding.UTF8.GetString(receiveBuffer, 0, dataReceived);
Console.WriteLine($"Received: {receivedText}");
var response = Encoding.UTF8.GetBytes($"REPLY: {receivedText}");
await dataStream.WriteAsync(response, 0, response.Length);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Connection error: {ex.Message}");
}
}
}
TCP Client Implementation
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
public class NetworkClient
{
private readonly TcpClient _connection;
private readonly NetworkStream _dataStream;
public NetworkClient(string hostAddress, int portNumber)
{
_connection = new TcpClient();
_connection.Connect(hostAddress, portNumber);
_dataStream = _connection.GetStream();
}
public async Task TransmitAsync(string payload)
{
try
{
var messageBytes = Encoding.UTF8.GetBytes(payload);
await _dataStream.WriteAsync(messageBytes, 0, messageBytes.Length);
Console.WriteLine($"Sent: {payload}");
var replyBuffer = new byte[4096];
int bytesRead = await _dataStream.ReadAsync(replyBuffer, 0, replyBuffer.Length);
var serverReply = Encoding.UTF8.GetString(replyBuffer, 0, bytesRead);
Console.WriteLine($"Server reply: {serverReply}");
}
catch (Exception ex)
{
Console.WriteLine($"Transmission failed: {ex.Message}");
}
}
public void Terminate()
{
_dataStream?.Close();
_connection?.Close();
}
}
Usage Examples
Server Initialization
var server = new NetworkServer(8080);
await server.BeginListeningAsync();
Client Connection
using var client = new NetworkClient("localhost", 8080);
await client.TransmitAsync("Test message from client");
client.Terminate();
Core Implementation Features
Asynchronous Communicatoin Enhancement
public async Task ManageClientConnectionAsync(TcpClient clientSocket)
{
using (clientSocket)
using (var stream = clientSocket.GetStream())
{
var buffer = ArrayPool<byte>.Shared.Rent(4096);
try
{
while (true)
{
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0) break;
var message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
await HandleIncomingDataAsync(clientSocket, message);
}
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
}
}
Robust Error Handling
try
{
// Network operations
}
catch (SocketException socketEx) when (socketEx.SocketErrorCode == SocketError.ConnectionAborted)
{
Console.WriteLine("Client abruptly disconnected");
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation cancelled by user");
}
Length-Prefixed Protocol Implemantation
// Sending with length prefix
var dataToSend = Encoding.UTF8.GetBytes("Message content");
var lengthPrefix = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(dataToSend.Length));
await networkStream.WriteAsync(lengthPrefix, 0, lengthPrefix.Length);
await networkStream.WriteAsync(dataToSend, 0, dataToSend.Length);
// Receiving with length prefix
var lengthBuffer = new byte[4];
await ReadExactAsync(networkStream, lengthBuffer, 0, 4);
var messageLength = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(lengthBuffer, 0));
var messageBuffer = new byte[messageLength];
await ReadExactAsync(networkStream, messageBuffer, 0, messageLength);
Performance Optimization Strategies
Memory Pool Management
var rentedBuffer = MemoryPool<byte>.Shared.Rent(4096);
try
{
// Perform I/O operations with rentedBuffer
}
finally
{
MemoryPool<byte>.Shared.Return(rentedBuffer);
}
Connection Pooling
public class ConnectionPoolManager
{
private readonly ConcurrentBag<TcpClient> _availableConnections = new();
public async Task<TcpClient> AcquireConnectionAsync(string host, int port)
{
if (!_availableConnections.TryTake(out var connection))
{
connection = new TcpClient();
await connection.ConnectAsync(host, port);
}
return connection;
}
public void ReleaseConnection(TcpClient connection)
{
if (connection.Connected)
{
_availableConnections.Add(connection);
}
}
}
Concurrency Control
private readonly SemaphoreSlim _connectionLimiter = new(50);
public async Task ProcessClientAsync(TcpClient client)
{
await _connectionLimiter.WaitAsync();
try
{
// Handle client processing
}
finally
{
_connectionLimiter.Release();
}
}
Project Architecture
TcpNetworkApplication/
├── ServerSide/
│ ├── ServerProgram.cs // Server entry point
│ └── TcpNetworkServer.cs // Core server logic
├── ClientSide/
│ ├── ClientProgram.cs // Client entry point
│ └── TcpNetworkClient.cs // Client implementation
├── Protocol/
│ └── CommunicationProtocol.cs // Message protocol definitions
└── UnitTests/
└── NetworkTests.cs // Test suite
Monitoring and Diagnostics
Logging Framework
public interface INetworkLogger
{
void LogInfo(string message);
void LogError(Exception ex, string context);
}
public class FileNetworkLogger : INetworkLogger
{
private readonly string _logPath;
public void LogInfo(string message)
{
File.AppendAllText(_logPath, $"[{DateTime.UtcNow}] INFO: {message}{Environment.NewLine}");
}
}
Advanced Features
Heartbeat Mechanism
private async Task MaintainConnectionAsync()
{
var heartbeatInterval = TimeSpan.FromSeconds(30);
using var timer = new PeriodicTimer(heartbeatInterval);
while (await timer.WaitForNextTickAsync())
{
try
{
await _dataStream.WriteAsync(Encoding.UTF8.GetBytes("PING"));
}
catch (Exception ex)
{
Console.WriteLine($"Heartbeat failed: {ex.Message}");
break;
}
}
}
Secure Communication Layer
private async Task EstablishSecureConnectionAsync()
{
var secureStream = new SslStream(_dataStream, false);
var sslOptions = new SslClientAuthenticationOptions
{
TargetHost = Dns.GetHostName(),
EnabledSslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12,
RemoteCertificateValidationCallback = (sender, cert, chain, errors) => true
};
await secureStream.AuthenticateAsClientAsync(sslOptions);
return secureStream;
}