C# 网络编程深度分析
目录
网络编程基础
OSI七层模型与.NET网络栈
应用层 ─── HTTP/FTP/SMTP (HttpClient, WebClient)
表示层 ─── SSL/TLS (SslStream)
会话层 ─── Socket会话管理
传输层 ─── TCP/UDP (TcpClient, UdpClient, Socket)
网络层 ─── IP (IPAddress, IPEndPoint)
数据链路层 ─── 以太网/WiFi
物理层 ─── 硬件
.NET网络编程层次结构
HttpClient → WebRequest → ServicePoint
TcpClient/UdpClient → NetworkStream
Socket → Winsock API
Socket编程详解
Socket基础概念
Socket类型
Socket tcpSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
Socket udpSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram,
ProtocolType.Udp);
Socket rawSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Raw,
ProtocolType.Icmp);
地址族与协议
public enum AddressFamily
{
InterNetwork = 2,
InterNetworkV6 = 23,
Unix = 1,
}
public enum ProtocolType
{
Tcp = 6,
Udp = 17,
Icmp = 1,
}
TCP Socket编程
服务端实现
public class TcpServer
{
private Socket serverSocket;
private readonly List<Socket> clients = new List<Socket>();
public async Task StartAsync(IPEndPoint endPoint)
{
serverSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
serverSocket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReuseAddress, true);
serverSocket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.KeepAlive, true);
serverSocket.Bind(endPoint);
serverSocket.Listen(100);
Console.WriteLine($"服务器启动在 {endPoint}");
_ = Task.Run(AcceptClientsAsync);
}
private async Task AcceptClientsAsync()
{
while (true)
{
try
{
var clientSocket = await AcceptAsync();
lock (clients)
{
clients.Add(clientSocket);
}
_ = Task.Run(() => HandleClientAsync(clientSocket));
}
catch (Exception ex)
{
Console.WriteLine($"接受连接错误: {ex.Message}");
}
}
}
private Task<Socket> AcceptAsync()
{
return Task.Factory.FromAsync(
serverSocket.BeginAccept,
serverSocket.EndAccept,
null);
}
private async Task HandleClientAsync(Socket client)
{
var buffer = new byte[4096];
try
{
while (client.Connected)
{
int received = await ReceiveAsync(client, buffer);
if (received == 0) break;
var message = Encoding.UTF8.GetString(buffer, 0, received);
Console.WriteLine($"收到消息: {message}");
await SendAsync(client, buffer, received);
}
}
catch (Exception ex)
{
Console.WriteLine($"处理客户端错误: {ex.Message}");
}
finally
{
lock (clients)
{
clients.Remove(client);
}
client.Close();
}
}
private Task<int> ReceiveAsync(Socket socket, byte[] buffer)
{
return Task.Factory.FromAsync<int>(
(callback, state) => socket.BeginReceive(buffer, 0, buffer.Length,
SocketFlags.None, callback, state),
socket.EndReceive,
null);
}
private Task<int> SendAsync(Socket socket, byte[] buffer, int count)
{
return Task.Factory.FromAsync<int>(
(callback, state) => socket.BeginSend(buffer, 0, count,
SocketFlags.None, callback, state),
socket.EndSend,
null);
}
}
客户端实现
public class TcpClient
{
private Socket clientSocket;
public async Task ConnectAsync(IPEndPoint serverEndPoint)
{
clientSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
clientSocket.ReceiveTimeout = 30000;
clientSocket.SendTimeout = 30000;
await ConnectAsync(serverEndPoint);
Console.WriteLine($"连接到服务器 {serverEndPoint}");
_ = Task.Run(ReceiveMessagesAsync);
}
private Task ConnectAsync(IPEndPoint endPoint)
{
return Task.Factory.FromAsync(
(callback, state) => clientSocket.BeginConnect(endPoint, callback, state),
clientSocket.EndConnect,
null);
}
public async Task SendMessageAsync(string message)
{
var buffer = Encoding.UTF8.GetBytes(message);
await SendAsync(buffer);
}
private Task SendAsync(byte[] buffer)
{
return Task.Factory.FromAsync<int>(
(callback, state) => clientSocket.BeginSend(buffer, 0, buffer.Length,
SocketFlags.None, callback, state),
clientSocket.EndSend,
null);
}
private async Task ReceiveMessagesAsync()
{
var buffer = new byte[4096];
try
{
while (clientSocket.Connected)
{
int received = await ReceiveAsync(buffer);
if (received == 0) break;
var message = Encoding.UTF8.GetString(buffer, 0, received);
Console.WriteLine($"收到服务器消息: {message}");
}
}
catch (Exception ex)
{
Console.WriteLine($"接收消息错误: {ex.Message}");
}
}
private Task<int> ReceiveAsync(byte[] buffer)
{
return Task.Factory.FromAsync<int>(
(callback, state) => clientSocket.BeginReceive(buffer, 0, buffer.Length,
SocketFlags.None, callback, state),
clientSocket.EndReceive,
null);
}
}
UDP Socket编程
UDP服务端
public class UdpServer
{
private Socket udpSocket;
private readonly ConcurrentDictionary<EndPoint, DateTime> clients =
new ConcurrentDictionary<EndPoint, DateTime>();
public async Task StartAsync(IPEndPoint endPoint)
{
udpSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram,
ProtocolType.Udp);
udpSocket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReuseAddress, true);
udpSocket.ReceiveBufferSize = 65536;
udpSocket.SendBufferSize = 65536;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
const uint IOC_IN = 0x80000000;
const uint IOC_VENDOR = 0x18000000;
uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
udpSocket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { 0 }, null);
}
udpSocket.Bind(endPoint);
Console.WriteLine($"UDP服务器启动在 {endPoint}");
_ = Task.Run(ReceiveMessagesAsync);
_ = Task.Run(CleanupClientsAsync);
}
private async Task ReceiveMessagesAsync()
{
var buffer = new byte[65536];
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
while (true)
{
try
{
var result = await ReceiveFromAsync(buffer, remoteEndPoint);
var receivedBytes = result.ReceivedBytes;
var sender = result.RemoteEndPoint;
clients[sender] = DateTime.Now;
var message = Encoding.UTF8.GetString(buffer, 0, receivedBytes);
Console.WriteLine($"收到来自 {sender} 的消息: {message}");
var response = $"Echo: {message}";
await SendToAsync(Encoding.UTF8.GetBytes(response), sender);
}
catch (Exception ex)
{
Console.WriteLine($"接收UDP消息错误: {ex.Message}");
}
}
}
private Task<UdpReceiveResult> ReceiveFromAsync(byte[] buffer, EndPoint remoteEndPoint)
{
var tcs = new TaskCompletionSource<UdpReceiveResult>();
udpSocket.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None,
ref remoteEndPoint, ar =>
{
try
{
EndPoint endPoint = new IPEndPoint(IPAddress.Any, 0);
int receivedBytes = udpSocket.EndReceiveFrom(ar, ref endPoint);
tcs.SetResult(new UdpReceiveResult
{
ReceivedBytes = receivedBytes,
RemoteEndPoint = endPoint
});
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}, null);
return tcs.Task;
}
private Task SendToAsync(byte[] buffer, EndPoint remoteEndPoint)
{
return Task.Factory.FromAsync<int>(
(callback, state) => udpSocket.BeginSendTo(buffer, 0, buffer.Length,
SocketFlags.None, remoteEndPoint,
callback, state),
udpSocket.EndSendTo,
null);
}
private async Task CleanupClientsAsync()
{
while (true)
{
await Task.Delay(30000);
var timeout = DateTime.Now.AddMinutes(-5);
var expiredClients = clients.Where(kvp => kvp.Value < timeout)
.Select(kvp => kvp.Key)
.ToList();
foreach (var client in expiredClients)
{
clients.TryRemove(client, out _);
Console.WriteLine($"清理超时客户端: {client}");
}
}
}
public struct UdpReceiveResult
{
public int ReceivedBytes;
public EndPoint RemoteEndPoint;
}
}
TCP vs UDP 对比
特性对比表
特性 | TCP | UDP |
---|
连接性 | 面向连接 | 无连接 |
可靠性 | 可靠传输 | 不可靠传输 |
顺序保证 | 保证顺序 | 不保证顺序 |
流量控制 | 有 | 无 |
拥塞控制 | 有 | 无 |
头部开销 | 20字节+ | 8字节 |
传输效率 | 较低 | 较高 |
适用场景 | 文件传输、网页浏览 | 视频直播、游戏 |
使用场景选择
选择TCP的场景:
- 文件传输: 确保数据完整性
- Web应用: HTTP/HTTPS协议
- 邮件系统: SMTP/POP3/IMAP
- 数据库连接: 确保事务完整性
- 聊天应用: 消息不能丢失
选择UDP的场景:
- 实时游戏: 低延迟优先
- 视频直播: 偶尔丢帧可接受
- DNS查询: 快速响应
- 传感器数据: 最新数据更重要
- 广播/组播: 一对多通信
异步编程模式
演进历程
int result = socket.Receive(buffer);
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None,
callback, state);
var args = new SocketAsyncEventArgs();
args.SetBuffer(buffer, 0, buffer.Length);
args.Completed += OnReceiveCompleted;
socket.ReceiveAsync(args);
int result = await socket.ReceiveAsync(buffer, SocketFlags.None);
现代异步模式详解
SocketAsyncEventArgs 模式
public class HighPerformanceServer
{
private Socket listenSocket;
private readonly ObjectPool<SocketAsyncEventArgs> receiveArgsPool;
private readonly ObjectPool<SocketAsyncEventArgs> sendArgsPool;
private readonly SemaphoreSlim maxConnectionsSemaphore;
public HighPerformanceServer(int maxConnections)
{
maxConnectionsSemaphore = new SemaphoreSlim(maxConnections, maxConnections);
receiveArgsPool = new ObjectPool<SocketAsyncEventArgs>(
() => CreateReceiveEventArgs(),
maxConnections);
sendArgsPool = new ObjectPool<SocketAsyncEventArgs>(
() => CreateSendEventArgs(),
maxConnections);
}
private SocketAsyncEventArgs CreateReceiveEventArgs()
{
var args = new SocketAsyncEventArgs();
args.SetBuffer(new byte[4096], 0, 4096);
args.Completed += OnReceiveCompleted;
return args;
}
private SocketAsyncEventArgs CreateSendEventArgs()
{
var args = new SocketAsyncEventArgs();
args.Completed += OnSendCompleted;
return args;
}
public async Task StartAsync(IPEndPoint endPoint)
{
listenSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
listenSocket.Bind(endPoint);
listenSocket.Listen(100);
StartAccept(null);
}
private void StartAccept(SocketAsyncEventArgs acceptArgs)
{
if (acceptArgs == null)
{
acceptArgs = new SocketAsyncEventArgs();
acceptArgs.Completed += OnAcceptCompleted;
}
else
{
acceptArgs.AcceptSocket = null;
}
maxConnectionsSemaphore.Wait();
bool willRaiseEvent = listenSocket.AcceptAsync(acceptArgs);
if (!willRaiseEvent)
{
ProcessAccept(acceptArgs);
}
}
private void OnAcceptCompleted(object sender, SocketAsyncEventArgs e)
{
ProcessAccept(e);
}
private void ProcessAccept(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
var receiveArgs = receiveArgsPool.Get();
receiveArgs.UserToken = e.AcceptSocket;
StartReceive(receiveArgs);
}
StartAccept(e);
}
private void StartReceive(SocketAsyncEventArgs receiveArgs)
{
var socket = (Socket)receiveArgs.UserToken;
bool willRaiseEvent = socket.ReceiveAsync(receiveArgs);
if (!willRaiseEvent)
{
ProcessReceive(receiveArgs);
}
}
private void OnReceiveCompleted(object sender, SocketAsyncEventArgs e)
{
ProcessReceive(e);
}
private void ProcessReceive(SocketAsyncEventArgs e)
{
var socket = (Socket)e.UserToken;
if (e.SocketError == SocketError.Success && e.BytesTransferred > 0)
{
ProcessReceivedData(e);
StartReceive(e);
}
else
{
CloseClientSocket(e);
}
}
private void ProcessReceivedData(SocketAsyncEventArgs e)
{
var sendArgs = sendArgsPool.Get();
sendArgs.UserToken = e.UserToken;
sendArgs.SetBuffer(e.Buffer, e.Offset, e.BytesTransferred);
var socket = (Socket)e.UserToken;
bool willRaiseEvent = socket.SendAsync(sendArgs);
if (!willRaiseEvent)
{
ProcessSend(sendArgs);
}
}
private void OnSendCompleted(object sender, SocketAsyncEventArgs e)
{
ProcessSend(e);
}
private void ProcessSend(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
sendArgsPool.Return(e);
}
else
{
CloseClientSocket(e);
}
}
private void CloseClientSocket(SocketAsyncEventArgs e)
{
var socket = (Socket)e.UserToken;
try
{
socket.Shutdown(SocketShutdown.Send);
socket.Close();
}
catch (Exception) { }
receiveArgsPool.Return(e);
maxConnectionsSemaphore.Release();
}
}
现代 async/await 模式
public class ModernAsyncServer
{
private TcpListener listener;
private readonly CancellationTokenSource cancellationTokenSource = new();
public async Task StartAsync(IPEndPoint endPoint)
{
listener = new TcpListener(endPoint);
listener.Start();
Console.WriteLine($"服务器启动在 {endPoint}");
await AcceptClientsAsync(cancellationTokenSource.Token);
}
private async Task AcceptClientsAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
var tcpClient = await listener.AcceptTcpClientAsync();
_ = HandleClientAsync(tcpClient, cancellationToken);
}
catch (ObjectDisposedException)
{
break;
}
catch (Exception ex)
{
Console.WriteLine($"接受连接错误: {ex.Message}");
}
}
}
private async Task HandleClientAsync(TcpClient client, CancellationToken cancellationToken)
{
using (client)
using (var stream = client.GetStream())
{
var buffer = new byte[4096];
try
{
while (!cancellationToken.IsCancellationRequested && client.Connected)
{
int bytesRead = await stream.ReadAsync(buffer, cancellationToken);
if (bytesRead == 0) break;
var message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Console.WriteLine($"收到消息: {message}");
var response = $"Echo: {message}";
var responseBytes = Encoding.UTF8.GetBytes(response);
await stream.WriteAsync(responseBytes, cancellationToken);
}
}
catch (Exception ex) when (!(ex is OperationCanceledException))
{
Console.WriteLine($"处理客户端错误: {ex.Message}");
}
}
}
public void Stop()
{
cancellationTokenSource.Cancel();
listener?.Stop();
}
}
网络性能优化
1. 缓冲区优化
Socket缓冲区设置
public static void OptimizeSocketBuffers(Socket socket)
{
socket.SendBufferSize = 65536;
socket.ReceiveBufferSize = 65536;
socket.SetSocketOption(SocketOptionLevel.Tcp,
SocketOptionName.NoDelay, true);
socket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.KeepAlive, true);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
byte[] keepAlive = new byte[12];
BitConverter.GetBytes(1).CopyTo(keepAlive, 0);
BitConverter.GetBytes(30000).CopyTo(keepAlive, 4);
BitConverter.GetBytes(1000).CopyTo(keepAlive, 8);
socket.IOControl(IOControlCode.KeepAliveValues, keepAlive, null);
}
}
内存池使用
public class BufferManager
{
private readonly ArrayPool<byte> arrayPool;
private readonly int bufferSize;
public BufferManager(int bufferSize = 4096)
{
this.bufferSize = bufferSize;
this.arrayPool = ArrayPool<byte>.Shared;
}
public byte[] RentBuffer()
{
return arrayPool.Rent(bufferSize);
}
public void ReturnBuffer(byte[] buffer)
{
arrayPool.Return(buffer, clearArray: true);
}
}
public async Task<string> ReceiveMessageAsync(NetworkStream stream)
{
var bufferManager = new BufferManager();
var buffer = bufferManager.RentBuffer();
try
{
int bytesRead = await stream.ReadAsync(buffer);
return Encoding.UTF8.GetString(buffer, 0, bytesRead);
}
finally
{
bufferManager.ReturnBuffer(buffer);
}
}
2. 连接池管理
public class ConnectionPool<T> : IDisposable where T : class
{
private readonly ConcurrentQueue<T> connections = new();
private readonly Func<Task<T>> connectionFactory;
private readonly Action<T> connectionReset;
private readonly int maxSize;
private volatile int currentCount;
public ConnectionPool(
Func<Task<T>> connectionFactory,
Action<T> connectionReset = null,
int maxSize = 100)
{
this.connectionFactory = connectionFactory;
this.connectionReset = connectionReset;
this.maxSize = maxSize;
}
public async Task<T> GetConnectionAsync()
{
if (connections.TryDequeue(out T connection))
{
connectionReset?.Invoke(connection);
return connection;
}
return await connectionFactory();
}
public void ReturnConnection(T connection)
{
if (connection == null) return;
if (currentCount < maxSize)
{
connections.Enqueue(connection);
Interlocked.Increment(ref currentCount);
}
else
{
if (connection is IDisposable disposable)
{
disposable.Dispose();
}
}
}
public void Dispose()
{
while (connections.TryDequeue(out T connection))
{
if (connection is IDisposable disposable)
{
disposable.Dispose();
}
}
}
}
public class HttpClientPool
{
private readonly ConnectionPool<HttpClient> pool;
public HttpClientPool()
{
pool = new ConnectionPool<HttpClient>(
connectionFactory: () => Task.FromResult(new HttpClient()),
connectionReset: client => { },
maxSize: 50
);
}
public async Task<string> GetAsync(string url)
{
var client = await pool.GetConnectionAsync();
try
{
return await client.GetStringAsync(url);
}
finally
{
pool.ReturnConnection(client);
}
}
}
3. 批量处理优化
public class BatchProcessor<T>
{
private readonly List<T> batch = new();
private readonly int batchSize;
private readonly TimeSpan flushInterval;
private readonly Func<IEnumerable<T>, Task> processor;
private readonly Timer flushTimer;
private readonly object lockObject = new();
public BatchProcessor(
int batchSize,
TimeSpan flushInterval,
Func<IEnumerable<T>, Task> processor)
{
this.batchSize = batchSize;
this.flushInterval = flushInterval;
this.processor = processor;
flushTimer = new Timer(TimerCallback, null, flushInterval, flushInterval);
}
public async Task AddAsync(T item)
{
List<T> itemsToProcess = null;
lock (lockObject)
{
batch.Add(item);
if (batch.Count >= batchSize)
{
itemsToProcess = new List<T>(batch);
batch.Clear();
}
}
if (itemsToProcess != null)
{
await processor(itemsToProcess);
}
}
private async void TimerCallback(object state)
{
List<T> itemsToProcess = null;
lock (lockObject)
{
if (batch.Count > 0)
{
itemsToProcess = new List<T>(batch);
batch.Clear();
}
}
if (itemsToProcess != null)
{
await processor(itemsToProcess);
}
}
public async Task FlushAsync()
{
List<T> itemsToProcess = null;
lock (lockObject)
{
if (batch.Count > 0)
{
itemsToProcess = new List<T>(batch);
batch.Clear();
}
}
if (itemsToProcess != null)
{
await processor(itemsToProcess);
}
}
public void Dispose()
{
flushTimer?.Dispose();
FlushAsync().Wait();
}
}
public class NetworkMessageSender
{
private readonly BatchProcessor<NetworkMessage> batchProcessor;
private readonly Socket socket;
public NetworkMessageSender(Socket socket)
{
this.socket = socket;
batchProcessor = new BatchProcessor<NetworkMessage>(
batchSize: 100,
flushInterval: TimeSpan.FromMilliseconds(10),
processor: SendBatchAsync
);
}
public async Task SendMessageAsync(NetworkMessage message)
{
await batchProcessor.AddAsync(message);
}
private async Task SendBatchAsync(IEnumerable<NetworkMessage> messages)
{
var messageList = messages.ToList();
if (messageList.Count == 0) return;
var batchData = SerializeBatch(messageList);
await SendAsync(batchData);
}
private byte[] SerializeBatch(List<NetworkMessage> messages)
{
using var stream = new MemoryStream();
using var writer = new BinaryWriter(stream);
writer.Write(messages.Count);
foreach (var message in messages)
{
var data = message.Serialize();
writer.Write(data.Length);
writer.Write(data);
}
return stream.ToArray();
}
private async Task SendAsync(byte[] data)
{
await Task.Factory.FromAsync(
(callback, state) => socket.BeginSend(data, 0, data.Length,
SocketFlags.None, callback, state),
socket.EndSend,
null);
}
}
常见问题与解决方案
1. 内存泄漏问题
问题:Socket未正确释放
public void BadExample()
{
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(new IPEndPoint(IPAddress.Loopback, 8080));
}
public async Task GoodExample()
{
using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
await ConnectAsync(socket, new IPEndPoint(IPAddress.Loopback, 8080));
}
问题:事件处理器未移除
public class BadEventHandler
{
private Socket socket;
public void Subscribe()
{
var args = new SocketAsyncEventArgs();
args.Completed += OnCompleted;
}
private void OnCompleted(object sender, SocketAsyncEventArgs e)
{
}
}
public class GoodEventHandler : IDisposable
{
private SocketAsyncEventArgs args;
public void Subscribe()
{
args = new SocketAsyncEventArgs();
args.Completed += OnCompleted;
}
private void OnCompleted(object sender, SocketAsyncEventArgs e)
{
}
public void Dispose()
{
if (args != null)
{
args.Completed -= OnCompleted;
args.Dispose();
}
}
}
2. 线程安全问题
问题:并发访问共享状态
public class UnsafeCounter
{
private int count = 0;
public void Increment()
{
count++;
}
public int GetCount()
{
return count;
}
}
public class SafeCounter
{
private long count = 0;
public void Increment()
{
Interlocked.Increment(ref count);
}
public long GetCount()
{
return Interlocked.Read(ref count);
}
}
public class ConcurrentConnectionManager
{
private readonly ConcurrentDictionary<string, Socket> connections
= new ConcurrentDictionary<string, Socket>();
public void AddConnection(string id, Socket socket)
{
connections.TryAdd(id, socket);
}
public bool RemoveConnection(string id)
{
return connections.TryRemove(id, out _);
}
public Socket GetConnection(string id)
{
connections.TryGetValue(id, out Socket socket);
return socket;
}
}
3. 异常处理最佳实践
public class RobustNetworkClient
{
private readonly ILogger logger;
private readonly RetryPolicy retryPolicy;
public RobustNetworkClient(ILogger logger)
{
this.logger = logger;
this.retryPolicy = new RetryPolicy(maxAttempts: 3, delay: TimeSpan.FromSeconds(1));
}
public async Task<T> SendWithRetryAsync<T>(
Func<Task<T>> operation,
CancellationToken cancellationToken = default)
{
return await retryPolicy.ExecuteAsync(async () =>
{
try
{
return await operation();
}
catch (SocketException ex) when (IsRetriableError(ex))
{
logger.LogWarning($"网络操作失败,将重试: {ex.Message}");
throw;
}
catch (TimeoutException ex)
{
logger.LogWarning($"操作超时,将重试: {ex.Message}");
throw;
}
catch (Exception ex)
{
logger.LogError(ex, "网络操作发生不可重试的错误");
throw;
}
}, cancellationToken);
}
private static bool IsRetriableError(SocketException ex)
{
return ex.SocketErrorCode switch
{
SocketError.NetworkDown => true,
SocketError.NetworkUnreachable => true,
SocketError.HostDown => true,
SocketError.HostUnreachable => true,
SocketError.ConnectionRefused => true,
SocketError.TimedOut => true,
_ => false
};
}
}
public class RetryPolicy
{
private readonly int maxAttempts;
private readonly TimeSpan delay;
public RetryPolicy(int maxAttempts, TimeSpan delay)
{
this.maxAttempts = maxAttempts;
this.delay = delay;
}
public async Task<T> ExecuteAsync<T>(
Func<Task<T>> operation,
CancellationToken cancellationToken = default)
{
Exception lastException = null;
for (int attempt = 1; attempt <= maxAttempts; attempt++)
{
try
{
return await operation();
}
catch (Exception ex)
{
lastException = ex;
if (attempt == maxAttempts)
{
throw new AggregateException($"操作在{maxAttempts}次尝试后失败", ex);
}
await Task.Delay(delay * attempt, cancellationToken);
}
}
throw lastException;
}
}
4. 性能监控与诊断
public class NetworkPerformanceMonitor
{
private readonly IMetricsCollector metricsCollector;
private long totalBytesSent;
private long totalBytesReceived;
private long totalConnections;
private long activeConnections;
public NetworkPerformanceMonitor(IMetricsCollector metricsCollector)
{
this.metricsCollector = metricsCollector;
_ = Task.Run(ReportMetricsAsync);
}
public void OnDataSent(int bytes)
{
Interlocked.Add(ref totalBytesSent, bytes);
metricsCollector.Counter("network_bytes_sent").Increment(bytes);
}
public void OnDataReceived(int bytes)
{
Interlocked.Add(ref totalBytesReceived, bytes);
metricsCollector.Counter("network_bytes_received").Increment(bytes);
}
public void OnConnectionEstablished()
{
Interlocked.Increment(ref totalConnections);
Interlocked.Increment(ref activeConnections);
metricsCollector.Gauge("active_connections").Set(activeConnections);
}
public void OnConnectionClosed()
{
Interlocked.Decrement(ref activeConnections);
metricsCollector.Gauge("active_connections").Set(activeConnections);
}
private async Task ReportMetricsAsync()
{
while (true)
{
await Task.Delay(TimeSpan.FromMinutes(1));
metricsCollector.Gauge("total_bytes_sent").Set(totalBytesSent);
metricsCollector.Gauge("total_bytes_received").Set(totalBytesReceived);
metricsCollector.Gauge("total_connections").Set(totalConnections);
}
}
}
public class MonitoredTcpServer
{
private readonly NetworkPerformanceMonitor monitor;
public MonitoredTcpServer(NetworkPerformanceMonitor monitor)
{
this.monitor = monitor;
}
private async Task HandleClientAsync(Socket client)
{
monitor.OnConnectionEstablished();
try
{
var buffer = new byte[4096];
while (client.Connected)
{
int received = await ReceiveAsync(client, buffer);
if (received == 0) break;
monitor.OnDataReceived(received);
var response = ProcessData(buffer, received);
await SendAsync(client, response);
monitor.OnDataSent(response.Length);
}
}
finally
{
monitor.OnConnectionClosed();
client.Close();
}
}
}
最佳实践
1. 架构设计原则
分层架构
┌─────────────────────────────────────┐
│ 应用层 (Application) │
├─────────────────────────────────────┤
│ 传输层 (Transport) │
├─────────────────────────────────────┤
│ 协议层 (Protocol) │
├─────────────────────────────────────┤
│ 网络层 (Network) │
└─────────────────────────────────────┘
public interface INetworkTransport
{
Task<bool> SendAsync(byte[] data, EndPoint endpoint);
event Action<byte[], EndPoint> DataReceived;
}
public interface IProtocolHandler
{
Task<bool> SendMessageAsync<T>(T message, string targetId);
event Action<TMessage, string> MessageReceived<TMessage>;
}
public interface IMessageTransport
{
Task<TResponse> RequestAsync<TRequest, TResponse>(TRequest request, string targetId);
Task SendAsync<T>(T message, string targetId);
}
配置管理
public class NetworkConfiguration
{
public int MaxConnections { get; set; } = 1000;
public int ReceiveBufferSize { get; set; } = 65536;
public int SendBufferSize { get; set; } = 65536;
public TimeSpan ConnectionTimeout { get; set; } = TimeSpan.FromSeconds(30);
public TimeSpan KeepAliveInterval { get; set; } = TimeSpan.FromSeconds(30);
public int MaxRetryAttempts { get; set; } = 3;
public TimeSpan RetryDelay { get; set; } = TimeSpan.FromSeconds(1);
public bool EnableNagleAlgorithm { get; set; } = false;
public bool EnableCompression { get; set; } = true;
public CompressionLevel CompressionLevel { get; set; } = CompressionLevel.Optimal;
}
public class ConfigurableNetworkServer
{
private readonly NetworkConfiguration config;
public ConfigurableNetworkServer(NetworkConfiguration config)
{
this.config = config ?? throw new ArgumentNullException(nameof(config));
}
public Socket CreateOptimizedSocket()
{
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.ReceiveBufferSize = config.ReceiveBufferSize;
socket.SendBufferSize = config.SendBufferSize;
socket.ReceiveTimeout = (int)config.ConnectionTimeout.TotalMilliseconds;
socket.SendTimeout = (int)config.ConnectionTimeout.TotalMilliseconds;
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, !config.EnableNagleAlgorithm);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
return socket;
}
}
2. 错误处理策略
public enum NetworkErrorSeverity
{
Transient,
Persistent,
Fatal
}
public class NetworkErrorHandler
{
private readonly ILogger logger;
private readonly IMetricsCollector metrics;
public NetworkErrorHandler(ILogger logger, IMetricsCollector metrics)
{
this.logger = logger;
this.metrics = metrics;
}
public NetworkErrorSeverity ClassifyError(Exception exception)
{
return exception switch
{
SocketException sockEx => ClassifySocketError(sockEx),
TimeoutException => NetworkErrorSeverity.Transient,
ObjectDisposedException => NetworkErrorSeverity.Fatal,
OutOfMemoryException => NetworkErrorSeverity.Fatal,
ArgumentException => NetworkErrorSeverity.Fatal,
IOException ioEx => ClassifyIOError(ioEx),
_ => NetworkErrorSeverity.Persistent
};
}
private NetworkErrorSeverity ClassifySocketError(SocketException ex)
{
return ex.SocketErrorCode switch
{
SocketError.TimedOut => NetworkErrorSeverity.Transient,
SocketError.NetworkDown => NetworkErrorSeverity.Transient,
SocketError.NetworkUnreachable => NetworkErrorSeverity.Transient,
SocketError.HostDown => NetworkErrorSeverity.Transient,
SocketError.HostUnreachable => NetworkErrorSeverity.Transient,
SocketError.ConnectionRefused => NetworkErrorSeverity.Persistent,
SocketError.ConnectionReset => NetworkErrorSeverity.Persistent,
SocketError.ConnectionAborted => NetworkErrorSeverity.Persistent,
SocketError.AddressAlreadyInUse => NetworkErrorSeverity.Fatal,
SocketError.AddressNotAvailable => NetworkErrorSeverity.Fatal,
_ => NetworkErrorSeverity.Persistent
};
}
private NetworkErrorSeverity ClassifyIOError(IOException ex)
{
if (ex.InnerException is SocketException sockEx)
{
return ClassifySocketError(sockEx);
}
return NetworkErrorSeverity.Persistent;
}
public async Task<bool> HandleErrorAsync(Exception exception, string context)
{
var severity = ClassifyError(exception);
logger.LogError(exception, "网络错误发生在 {Context}, 严重程度: {Severity}",
context, severity);
metrics.Counter($"network_errors_{severity.ToString().ToLower()}").Increment();
switch (severity)
{
case NetworkErrorSeverity.Transient:
await Task.Delay(TimeSpan.FromMilliseconds(100));
return true;
case NetworkErrorSeverity.Persistent:
await Task.Delay(TimeSpan.FromSeconds(5));
return true;
case NetworkErrorSeverity.Fatal:
logger.LogCritical(exception, "致命网络错误,服务将停止");
return false;
default:
return false;
}
}
}
3. 消息序列化与压缩
public interface IMessageSerializer
{
byte[] Serialize<T>(T message);
T Deserialize<T>(byte[] data);
byte[] SerializeWithCompression<T>(T message);
T DeserializeWithCompression<T>(byte[] compressedData);
}
public class JsonMessageSerializer : IMessageSerializer
{
private readonly JsonSerializerSettings jsonSettings;
public JsonMessageSerializer()
{
jsonSettings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
NullValueHandling = NullValueHandling.Ignore,
DateFormatHandling = DateFormatHandling.IsoDateFormat
};
}
public byte[] Serialize<T>(T message)
{
var json = JsonConvert.SerializeObject(message, jsonSettings);
return Encoding.UTF8.GetBytes(json);
}
public T Deserialize<T>(byte[] data)
{
var json = Encoding.UTF8.GetString(data);
return JsonConvert.DeserializeObject<T>(json, jsonSettings);
}
public byte[] SerializeWithCompression<T>(T message)
{
var data = Serialize(message);
return CompressData(data);
}
public T DeserializeWithCompression<T>(byte[] compressedData)
{
var data = DecompressData(compressedData);
return Deserialize<T>(data);
}
private byte[] CompressData(byte[] data)
{
using var output = new MemoryStream();
using (var gzip = new GZipStream(output, CompressionLevel.Optimal))
{
gzip.Write(data, 0, data.Length);
}
return output.ToArray();
}
private byte[] DecompressData(byte[] compressedData)
{
using var input = new MemoryStream(compressedData);
using var gzip = new GZipStream(input, CompressionMode.Decompress);
using var output = new MemoryStream();
gzip.CopyTo(output);
return output.ToArray();
}
}
public class BinaryMessageSerializer : IMessageSerializer
{
public byte[] Serialize<T>(T message)
{
using var stream = new MemoryStream();
using var writer = new BinaryWriter(stream);
writer.Write(typeof(T).AssemblyQualifiedName);
var data = MessagePackSerializer.Serialize(message);
writer.Write(data.Length);
writer.Write(data);
return stream.ToArray();
}
public T Deserialize<T>(byte[] data)
{
using var stream = new MemoryStream(data);
using var reader = new BinaryReader(stream);
var typeName = reader.ReadString();
var type = Type.GetType(typeName);
var dataLength = reader.ReadInt32();
var messageData = reader.ReadBytes(dataLength);
return MessagePackSerializer.Deserialize<T>(messageData);
}
public byte[] SerializeWithCompression<T>(T message)
{
var data = Serialize(message);
return data.Length > 1024 ? CompressData(data) : data;
}
public T DeserializeWithCompression<T>(byte[] data)
{
if (IsCompressed(data))
{
data = DecompressData(data);
}
return Deserialize<T>(data);
}
private bool IsCompressed(byte[] data)
{
return data.Length > 2 && data[0] == 0x1F && data[1] == 0x8B;
}
private byte[] CompressData(byte[] data)
{
using var output = new MemoryStream();
using (var deflate = new DeflateStream(output, CompressionLevel.Fastest))
{
deflate.Write(data, 0, data.Length);
}
return output.ToArray();
}
private byte[] DecompressData(byte[] compressedData)
{
using var input = new MemoryStream(compressedData);
using var deflate = new DeflateStream(input, CompressionMode.Decompress);
using var output = new MemoryStream();
deflate.CopyTo(output);
return output.ToArray();
}
}
4. 安全性考虑
public class SecureNetworkServer
{
private readonly RSA serverPrivateKey;
private readonly ConcurrentDictionary<EndPoint, SecureSession> secureSessions;
private readonly ILogger logger;
public SecureNetworkServer(ILogger logger)
{
this.logger = logger;
this.serverPrivateKey = RSA.Create(2048);
this.secureSessions = new ConcurrentDictionary<EndPoint, SecureSession>();
}
public async Task<bool> EstablishSecureSessionAsync(Socket client)
{
try
{
var publicKey = serverPrivateKey.ExportRSAPublicKey();
await SendAsync(client, publicKey);
var encryptedSymmetricKey = await ReceiveAsync(client);
var symmetricKey = serverPrivateKey.Decrypt(encryptedSymmetricKey, RSAEncryptionPadding.OaepSHA256);
var session = new SecureSession
{
SymmetricKey = symmetricKey,
EstablishedAt = DateTime.UtcNow,
LastActivity = DateTime.UtcNow
};
secureSessions[client.RemoteEndPoint] = session;
var confirmation = EncryptData(Encoding.UTF8.GetBytes("SESSION_ESTABLISHED"), symmetricKey);
await SendAsync(client, confirmation);
logger.LogInformation("安全会话已建立: {RemoteEndPoint}", client.RemoteEndPoint);
return true;
}
catch (Exception ex)
{
logger.LogError(ex, "建立安全会话失败: {RemoteEndPoint}", client.RemoteEndPoint);
return false;
}
}
public async Task<byte[]> ReceiveSecureDataAsync(Socket client)
{
if (!secureSessions.TryGetValue(client.RemoteEndPoint, out var session))
{
throw new UnauthorizedAccessException("未建立安全会话");
}
var encryptedData = await ReceiveAsync(client);
var decryptedData = DecryptData(encryptedData, session.SymmetricKey);
session.LastActivity = DateTime.UtcNow;
return decryptedData;
}
public async Task SendSecureDataAsync(Socket client, byte[] data)
{
if (!secureSessions.TryGetValue(client.RemoteEndPoint, out var session))
{
throw new UnauthorizedAccessException("未建立安全会话");
}
var encryptedData = EncryptData(data, session.SymmetricKey);
await SendAsync(client, encryptedData);
session.LastActivity = DateTime.UtcNow;
}
private byte[] EncryptData(byte[] data, byte[] key)
{
using var aes = Aes.Create();
aes.Key = key;
aes.GenerateIV();
using var encryptor = aes.CreateEncryptor();
using var output = new MemoryStream();
output.Write(aes.IV, 0, aes.IV.Length);
using (var cryptoStream = new CryptoStream(output, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(data, 0, data.Length);
}
return output.ToArray();
}
private byte[] DecryptData(byte[] encryptedData, byte[] key)
{
using var aes = Aes.Create();
aes.Key = key;
var iv = new byte[aes.BlockSize / 8];
Array.Copy(encryptedData, 0, iv, 0, iv.Length);
aes.IV = iv;
using var decryptor = aes.CreateDecryptor();
using var input = new MemoryStream(encryptedData, iv.Length, encryptedData.Length - iv.Length);
using var cryptoStream = new CryptoStream(input, decryptor, CryptoStreamMode.Read);
using var output = new MemoryStream();
cryptoStream.CopyTo(output);
return output.ToArray();
}
private async Task CleanupExpiredSessionsAsync()
{
while (true)
{
await Task.Delay(TimeSpan.FromMinutes(5));
var expiredTime = DateTime.UtcNow.AddMinutes(-30);
var expiredSessions = secureSessions
.Where(kvp => kvp.Value.LastActivity < expiredTime)
.Select(kvp => kvp.Key)
.ToList();
foreach (var endpoint in expiredSessions)
{
if (secureSessions.TryRemove(endpoint, out _))
{
logger.LogInformation("清理过期会话: {EndPoint}", endpoint);
}
}
}
}
}
public class SecureSession
{
public byte[] SymmetricKey { get; set; }
public DateTime EstablishedAt { get; set; }
public DateTime LastActivity { get; set; }
}
5. 负载均衡与故障转移
public interface ILoadBalancer
{
Task<EndPoint> GetNextEndpointAsync();
Task ReportHealthAsync(EndPoint endpoint, bool isHealthy);
}
public class RoundRobinLoadBalancer : ILoadBalancer
{
private readonly List<ServerEndpoint> endpoints;
private int currentIndex = 0;
private readonly object lockObject = new object();
public RoundRobinLoadBalancer(IEnumerable<EndPoint> endpoints)
{
this.endpoints = endpoints.Select(ep => new ServerEndpoint
{
EndPoint = ep,
IsHealthy = true,
Weight = 1
}).ToList();
_ = Task.Run(HealthCheckAsync);
}
public Task<EndPoint> GetNextEndpointAsync()
{
lock (lockObject)
{
var healthyEndpoints = endpoints.Where(e => e.IsHealthy).ToList();
if (healthyEndpoints.Count == 0)
{
throw new InvalidOperationException("没有可用的健康端点");
}
var endpoint = healthyEndpoints[currentIndex % healthyEndpoints.Count];
currentIndex = (currentIndex + 1) % healthyEndpoints.Count;
return Task.FromResult(endpoint.EndPoint);
}
}
public Task ReportHealthAsync(EndPoint endpoint, bool isHealthy)
{
var serverEndpoint = endpoints.FirstOrDefault(e => e.EndPoint.Equals(endpoint));
if (serverEndpoint != null)
{
lock (lockObject)
{
serverEndpoint.IsHealthy = isHealthy;
serverEndpoint.LastHealthCheck = DateTime.UtcNow;
}
}
return Task.CompletedTask;
}
private async Task HealthCheckAsync()
{
while (true)
{
foreach (var endpoint in endpoints)
{
try
{
var isHealthy = await PingEndpointAsync(endpoint.EndPoint);
await ReportHealthAsync(endpoint.EndPoint, isHealthy);
}
catch (Exception ex)
{
Console.WriteLine($"健康检查失败 {endpoint.EndPoint}: {ex.Message}");
await ReportHealthAsync(endpoint.EndPoint, false);
}
}
await Task.Delay(TimeSpan.FromSeconds(30));
}
}
private async Task<bool> PingEndpointAsync(EndPoint endpoint)
{
try
{
using var client = new TcpClient();
var connectTask = client.ConnectAsync(((IPEndPoint)endpoint).Address,
((IPEndPoint)endpoint).Port);
if (await Task.WhenAny(connectTask, Task.Delay(5000)) == connectTask)
{
return client.Connected;
}
return false;
}
catch
{
return false;
}
}
}
public class ServerEndpoint
{
public EndPoint EndPoint { get; set; }
public bool IsHealthy { get; set; }
public int Weight { get; set; }
public DateTime LastHealthCheck { get; set; }
public int CurrentConnections { get; set; }
}
public class WeightedRoundRobinLoadBalancer : ILoadBalancer
{
private readonly List<WeightedEndpoint> endpoints;
private readonly object lockObject = new object();
public WeightedRoundRobinLoadBalancer(IEnumerable<(EndPoint endpoint, int weight)> endpoints)
{
this.endpoints = endpoints.Select(e => new WeightedEndpoint
{
EndPoint = e.endpoint,
Weight = e.weight,
CurrentWeight = 0,
IsHealthy = true
}).ToList();
}
public Task<EndPoint> GetNextEndpointAsync()
{
lock (lockObject)
{
var healthyEndpoints = endpoints.Where(e => e.IsHealthy).ToList();
if (healthyEndpoints.Count == 0)
{
throw new InvalidOperationException("没有可用的健康端点");
}
var totalWeight = healthyEndpoints.Sum(e => e.Weight);
foreach (var endpoint in healthyEndpoints)
{
endpoint.CurrentWeight += endpoint.Weight;
}
var selected = healthyEndpoints.OrderByDescending(e => e.CurrentWeight).First();
selected.CurrentWeight -= totalWeight;
return Task.FromResult(selected.EndPoint);
}
}
public Task ReportHealthAsync(EndPoint endpoint, bool isHealthy)
{
var weightedEndpoint = endpoints.FirstOrDefault(e => e.EndPoint.Equals(endpoint));
if (weightedEndpoint != null)
{
lock (lockObject)
{
weightedEndpoint.IsHealthy = isHealthy;
}
}
return Task.CompletedTask;
}
}
public class WeightedEndpoint
{
public EndPoint EndPoint { get; set; }
public int Weight { get; set; }
public int CurrentWeight { get; set; }
public bool IsHealthy { get; set; }
}
public class FailoverNetworkClient
{
private readonly ILoadBalancer loadBalancer;
private readonly ILogger logger;
private readonly ConnectionPool<Socket> connectionPool;
private readonly SemaphoreSlim connectionSemaphore;
public FailoverNetworkClient(
ILoadBalancer loadBalancer,
ILogger logger,
int maxConnections = 100)
{
this.loadBalancer = loadBalancer;
this.logger = logger;
this.connectionSemaphore = new SemaphoreSlim(maxConnections, maxConnections);
this.connectionPool = new ConnectionPool<Socket>(
CreateConnectionAsync,
ResetConnection,
maxConnections
);
}
public async Task<TResponse> SendRequestAsync<TRequest, TResponse>(
TRequest request,
TimeSpan timeout = default)
{
if (timeout == default)
timeout = TimeSpan.FromSeconds(30);
var attempts = 0;
const int maxAttempts = 3;
while (attempts < maxAttempts)
{
Socket connection = null;
EndPoint endpoint = null;
try
{
endpoint = await loadBalancer.GetNextEndpointAsync();
await connectionSemaphore.WaitAsync(timeout);
connection = await connectionPool.GetConnectionAsync();
var response = await SendRequestInternalAsync<TRequest, TResponse>(
connection, request, timeout);
await loadBalancer.ReportHealthAsync(endpoint, true);
return response;
}
catch (Exception ex)
{
attempts++;
logger.LogWarning(ex,
"请求失败 (尝试 {Attempt}/{MaxAttempts}) 到端点 {Endpoint}: {Message}",
attempts, maxAttempts, endpoint, ex.Message);
if (endpoint != null)
{
await loadBalancer.ReportHealthAsync(endpoint, false);
}
if (connection != null)
{
try
{
connection.Close();
}
catch { }
}
if (attempts >= maxAttempts)
{
throw new AggregateException(
$"在{maxAttempts}次尝试后请求仍然失败", ex);
}
await Task.Delay(TimeSpan.FromMilliseconds(Math.Pow(2, attempts) * 100));
}
finally
{
if (connection != null)
{
connectionPool.ReturnConnection(connection);
}
connectionSemaphore.Release();
}
}
throw new InvalidOperationException("无法完成请求");
}
private async Task<Socket> CreateConnectionAsync()
{
var endpoint = await loadBalancer.GetNextEndpointAsync();
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.ReceiveTimeout = 30000;
socket.SendTimeout = 30000;
await ConnectAsync(socket, endpoint);
return socket;
}
private void ResetConnection(Socket socket)
{
if (!socket.Connected)
{
socket.Close();
throw new InvalidOperationException("连接已断开");
}
}
private async Task<TResponse> SendRequestInternalAsync<TRequest, TResponse>(
Socket socket,
TRequest request,
TimeSpan timeout)
{
var requestData = SerializeRequest(request);
await SendAsync(socket, requestData);
var responseData = await ReceiveAsync(socket, timeout);
return DeserializeResponse<TResponse>(responseData);
}
private byte[] SerializeRequest<T>(T request)
{
return JsonConvert.SerializeObject(request, Encoding.UTF8);
}
private T DeserializeResponse<T>(byte[] data)
{
var json = Encoding.UTF8.GetString(data);
return JsonConvert.DeserializeObject<T>(json);
}
private async Task ConnectAsync(Socket socket, EndPoint endpoint)
{
await Task.Factory.FromAsync(
(callback, state) => socket.BeginConnect(endpoint, callback, state),
socket.EndConnect,
null);
}
private async Task SendAsync(Socket socket, byte[] data)
{
await Task.Factory.FromAsync<int>(
(callback, state) => socket.BeginSend(data, 0, data.Length,
SocketFlags.None, callback, state),
socket.EndSend,
null);
}
private async Task<byte[]> ReceiveAsync(Socket socket, TimeSpan timeout)
{
using var cts = new CancellationTokenSource(timeout);
var buffer = new byte[4096];
var received = await Task.Factory.FromAsync<int>(
(callback, state) => socket.BeginReceive(buffer, 0, buffer.Length,
SocketFlags.None, callback, state),
socket.EndReceive,
null);
var result = new byte[received];
Array.Copy(buffer, result, received);
return result;
}
}
总结
关键要点
- 选择合适的协议:根据应用需求选择TCP或UDP
- 异步编程:使用现代async/await模式,避免阻塞线程
- 资源管理:正确释放Socket和相关资源,使用对象池减少GC压力
- 错误处理:实现健壮的错误处理和重试机制
- 性能优化:合理设置缓冲区大小,使用批处理和连接池
- 安全性:实现加密和身份验证机制
- 监控:添加性能监控和健康检查
- 可扩展性:设计支持负载均衡和故障转移的架构
技术栈推荐
- 高性能场景:Socket + SocketAsyncEventArgs
- 一般应用:TcpClient/UdpClient + async/await
- Web应用:HttpClient + HttpClientFactory
- 实时通信:SignalR 或自定义UDP协议
- 微服务:gRPC 或 RESTful API
性能基准
场景 | 推荐方案 | 典型性能 |
---|
高并发服务器 | Socket + EventArgs | 10K+ 连接 |
文件传输 | TCP + 大缓冲区 | 95%+ 带宽利用率 |
实时游戏 | UDP + 自定义协议 | <50ms 延迟 |
Web API | ASP.NET Core | 100K+ RPS |
消息队列 | TCP + 二进制协议 | 1M+ 消息/秒 |
这份文档涵盖了C#网络编程的核心概念、最佳实践和实际应用场景,可以作为开发高性能网络应用的参考指南。