HP-Socket压力测试例子,用恐怖如斯来形容。
HP-Socket是一套开源通用的高性能TCP/UDP/HTTP通信框架,由JessMA Open Source开发维护,支持多语言、跨平台,广泛应用于高并发网络通信场景开发。
一、核心工作原理
HP-Socket采用分层架构设计,基于平台最优的事件驱动模型,结合内存管理优化技术实现高性能通信:
- 分层架构:从底层到高层分为平台适配层、IO处理层、通信框架层、应用协议层,完整封装底层通信细节,与应用层完全解耦
- 平台适配模型:
- Server/Agent组件:Windows基于IOCP模型,Linux基于EPOLL模型,匹配平台原生高性能IO特性
- Client组件:基于Event Select/POLL模型,每个组件管理单个Socket连接,适用于小规模客户端场景
- 核心优化机制:
- 使用内存池+私有堆技术,减少内存分配开销和内存碎片,实现高效内存管理
- 支持PUSH/PULL/PACK三种接收模型,其中PACK模型可自动处理分包粘包,降低应用层处理复杂度
- 基于事件通知模型,通过回调函数处理连接建立、数据接收、连接关闭等网络事件,避免线程阻塞
- 标准工作流程:创建监听器→创建并绑定通信组件→启动组件→处理通信事件→停止组件→销毁组件
二、核心优势
1. 通用性与解耦设计
HP-Socket仅负责字节流的收发,不参与应用层协议解析,和应用程序通过接口交互且完全解耦,任何实现接口规范的应用都可以无缝整合。
2. 优异的易用性
- 接口设计简单统一,完全封装底层通信细节,应用无需干预底层操作
- 提供PUSH/PULL/PACK多种接收模型,可灵活选择封解包处理方式,降低出错概率
- 提供完整的示例代码(性能测试、多语言演示),开箱即用降低开发门槛。
3. 良好的伸缩性
应用可根据实际场景(容量需求、通信规模、资源状况)调整性能参数:包括工作线程数量、缓存池大小、收发模式等,优化资源配置,避免资源浪费。
4. 完善的功能支持
- 全协议覆盖:支持TCP/UDP/HTTP/HTTPS/WebSocket,UDP模式还提供可选ARQ可靠传输机制
- 跨平台兼容:原生支持Windows/Linux,v5.8+版本支持macOS和Android移动端
- 多语言接口:原生支持C/C++,扩展支持C#、Python、Java、Delphi、易语言等多种开发语言
- 企业级特性:支持数十万级并发连接,内置流量整形、监控统计、自动重连容错机制
上压测源码:
效果:

单机i7办公电脑居然能跑出接近50wQps的速度。
服务端 HPSocketTest.Server.exe源码:
using HPSocket; using HPSocket.Tcp; using HPSocketTest.Common; using System.Collections.Concurrent; using System.Diagnostics; using System.Runtime.InteropServices; namespace HPSocketTest.Server; class Program { // 响应缓冲区池,减少 GC private static readonly ConcurrentBag<byte[]> ResponsePool = new(); static async Task Main(string[] args) { Console.Title = "HPSocket TCP PACK Server - 压力测试服务端"; Console.WriteLine("╔══════════════════════════════════════════════════════════════╗"); Console.WriteLine("║ HPSocket.Net TCP PACK Server - 高性能压力测试服务端 ║"); Console.WriteLine("╚══════════════════════════════════════════════════════════════╝"); var cts = new CancellationTokenSource(); Console.CancelKeyPress += (s, e) => { e.Cancel = true; cts.Cancel(); }; // 配置参数 ushort port = args.Length > 0 && ushort.TryParse(args[0], out var p) ? p : (ushort)5555; int workerThreads = args.Length > 1 && int.TryParse(args[1], out var w) ? w : Environment.ProcessorCount * 2; // 初始化响应池 for (int i = 0; i < 200; i++) ResponsePool.Add(new byte[8192]); // 创建 PACK 服务端(非泛型) var server = new TcpPackServer() { // PACK 模型关键配置 PackHeaderFlag = 0x00, // 包头标志(不使用特殊标志) //PackHeaderSize = PacketHeader.HeaderSize, // 包头大小 16 字节 MaxPackSize = 65535, // 最大包大小 // 性能调优 SocketBufferSize = 65536, SocketListenQueue = 500, WorkerThreadCount = (uint)workerThreads, // 心跳检测 KeepAliveTime = 60000, KeepAliveInterval = 10000, Address="0.0.0.0", Port=port, }; var stats = new PerformanceStatistics(); var sw = Stopwatch.StartNew(); var clientInfo = new ConcurrentDictionary<IntPtr, ClientContext>(); // ===== 事件绑定 ===== server.OnPrepareListen += (sender, soListen) => { Console.WriteLine($"[准备监听] Socket: {soListen}, 工作线程: {workerThreads}"); return HandleResult.Ok; }; server.OnAccept += (sender, connId, client) => { stats.IncrementConnections(); string ip2; ushort port2; sender.GetRemoteAddress(connId, out ip2, out port2); var ctx = new ClientContext { ConnId = connId, ConnectTime = DateTime.Now, RemoteAddress = $"{ip2}:{port2}" }; clientInfo[connId] = ctx; Console.WriteLine($"[连接建立] {ctx.RemoteAddress} (总连接: {stats.ActiveConnections})"); return HandleResult.Ok; }; // OnReceive 收到的是完整数据包(不含包头),即只有包体 // 但我们在包头中放了命令信息,所以需要自己解析包头 // 实际上 PACK 模型的 OnReceive 参数 data 是【完整包数据(含包头)】 server.OnReceive += (sender, connId, data) => { try { stats.AddBytesReceived(data.Length); // PACK 模型下,data 是完整的数据包(含包头) if (data.Length < PacketHeader.HeaderSize) { stats.IncrementErrors(); return HandleResult.Error; } // 解析包头 var header = MemoryMarshal.Read<PacketHeader>(data.AsSpan()); if (!header.IsValid) { stats.IncrementErrors(); return HandleResult.Error; } stats.IncrementMessagesReceived(); // 根据命令处理 switch ((CommandType)header.Command) { case CommandType.EchoRequest: return HandleEcho(server, connId, header, data, stats); case CommandType.BenchmarkRequest: return HandleBenchmark(server, connId, header, data, stats); case CommandType.Heartbeat: return HandleHeartbeat(server, connId, header); default: return HandleResult.Ok; } } catch (Exception ex) { stats.IncrementErrors(); Console.WriteLine($"[处理异常] {ex.Message}"); return HandleResult.Error; } }; server.OnClose += (sender, connId, socketOperation, errorCode) => { stats.DecrementConnections(); if (clientInfo.TryRemove(connId, out var ctx)) { var duration = DateTime.Now - ctx.ConnectTime; Console.WriteLine($"[连接关闭] {ctx.RemoteAddress}, 存活: {duration.TotalSeconds:F1}s, 错误码: {errorCode}"); } return HandleResult.Ok; }; server.OnShutdown += (sender) => { Console.WriteLine("[服务关闭]"); return HandleResult.Ok; }; // 启动服务 if (!server.Start()) { Console.WriteLine($"[启动失败] {server.ErrorMessage}"); return; } Console.WriteLine($"[服务启动] 监听端口: {port}, PID: {Environment.ProcessId}"); Console.WriteLine("按 Ctrl+C 停止服务...\n"); // 统计输出任务 _ = Task.Run(async () => { while (!cts.Token.IsCancellationRequested) { await Task.Delay(5000, cts.Token); var elapsed = sw.Elapsed.TotalSeconds; var qps = elapsed > 0 ? stats.TotalMessagesReceived / elapsed : 0; var throughput = elapsed > 0 ? (stats.TotalBytesSent + stats.TotalBytesReceived) / elapsed / 1024 / 1024 : 0; Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] QPS: {qps:N0}/s | 吞吐: {throughput:F2} MB/s | {stats}"); } }, cts.Token); try { await Task.Delay(-1, cts.Token); } catch { } Console.WriteLine("\n[正在停止...]"); server.Stop(); Console.WriteLine($"[运行统计] 总时长: {sw.Elapsed}, {stats}"); } static HandleResult HandleEcho(ITcpPackServer server, IntPtr connId, PacketHeader header, byte[] data, PerformanceStatistics stats) { if (!ResponsePool.TryTake(out var buffer)) buffer = new byte[data.Length]; try { data.AsSpan().CopyTo(buffer); var respHeader = PacketHeader.Create( (ushort)CommandType.EchoResponse, header.BodyLength, header.Sequence); MemoryMarshal.Write(buffer.AsSpan(), ref respHeader); if (server.Send(connId, buffer, 0, PacketHeader.HeaderSize + (int)header.BodyLength)) { stats.IncrementMessagesSent(); stats.AddBytesSent(PacketHeader.HeaderSize + header.BodyLength); return HandleResult.Ok; } return HandleResult.Error; } finally { ResponsePool.Add(buffer); } } static HandleResult HandleBenchmark(ITcpPackServer server, IntPtr connId, PacketHeader header, byte[] data, PerformanceStatistics stats) { if (!ResponsePool.TryTake(out var buffer)) buffer = new byte[data.Length]; try { data.AsSpan().CopyTo(buffer); var respHeader = PacketHeader.Create( (ushort)CommandType.BenchmarkResponse, header.BodyLength, header.Sequence); MemoryMarshal.Write(buffer.AsSpan(), ref respHeader); if (server.Send(connId, buffer, 0, PacketHeader.HeaderSize + (int)header.BodyLength)) { stats.IncrementMessagesSent(); stats.AddBytesSent(PacketHeader.HeaderSize + header.BodyLength); return HandleResult.Ok; } return HandleResult.Error; } finally { ResponsePool.Add(buffer); } } static HandleResult HandleHeartbeat(ITcpPackServer server, IntPtr connId, PacketHeader header) { if (!ResponsePool.TryTake(out var buffer)) buffer = new byte[PacketHeader.HeaderSize]; try { var resp = PacketHeader.Create((ushort)CommandType.Heartbeat, 0, header.Sequence); MemoryMarshal.Write(buffer.AsSpan(), ref resp); server.Send(connId, buffer, 0, PacketHeader.HeaderSize); return HandleResult.Ok; } finally { ResponsePool.Add(buffer); } } } public class ClientContext { public IntPtr ConnId { get; set; } public DateTime ConnectTime { get; set; } public string RemoteAddress { get; set; } = ""; }
客户端 HPSocketTest.Client.exe源码:
using HPSocket; using HPSocket.Tcp; using HPSocketTest.Common; using System.Collections.Concurrent; using System.Diagnostics; using System.Runtime.InteropServices; namespace HPSocketTest.Client; class Program { static async Task Main(string[] args) { Console.Title = "HPSocket TCP PACK Client - 压力测试客户端"; Console.WriteLine("╔══════════════════════════════════════════════════════════════╗"); Console.WriteLine("║ HPSocket.Net TCP PACK Client - 并发压力测试客户端 ║"); Console.WriteLine("╚══════════════════════════════════════════════════════════════╝"); // 解析参数 var config = ParseArgs(args); Console.WriteLine($"[配置] 服务器: {config.Host}:{config.Port}"); Console.WriteLine($"[配置] 并发连接: {config.Connections}"); Console.WriteLine($"[配置] 消息大小: {config.MessageSize} bytes, 持续时间: {config.DurationSeconds}s"); Console.WriteLine($"[配置] 发送间隔: {config.SendIntervalMs}ms, 批量发送: {config.BatchSize}"); Console.WriteLine(); var cts = new CancellationTokenSource(); Console.CancelKeyPress += (s, e) => { e.Cancel = true; cts.Cancel(); }; // 全局统计 var globalStats = new PerformanceStatistics(); var latencyHistogram = new ConcurrentBag<double>(); var sw = Stopwatch.StartNew(); // 创建连接池 var clients = new List<BenchmarkClient>(); var connectionTasks = new List<Task>(); Console.WriteLine("[阶段1] 建立连接中..."); for (int i = 0; i < config.Connections; i++) { var client = new BenchmarkClient(config, globalStats, latencyHistogram); clients.Add(client); int connIndex = i; connectionTasks.Add(Task.Run(async () => { if (await client.ConnectAsync()) { if ((connIndex + 1) % 100 == 0 || connIndex == 0) Console.WriteLine($" 已建立 {connIndex + 1}/{config.Connections} 连接..."); } })); // 控制连接建立速率 if (i % 50 == 0) await Task.Delay(10); } await Task.WhenAll(connectionTasks); var connectedCount = clients.Count(c => c.IsConnected); Console.WriteLine($"[阶段1完成] 成功连接: {connectedCount}/{config.Connections}"); if (connectedCount == 0) { Console.WriteLine("[错误] 没有成功建立的连接,退出"); return; } Console.WriteLine("[阶段2] 开始压力测试..."); var testTasks = clients .Where(c => c.IsConnected) .Select(c => c.RunBenchmarkAsync(cts.Token)) .ToArray(); // 监控任务 var monitorTask = Task.Run(async () => { var lastSent = 0L; var lastRecv = 0L; var lastTime = sw.Elapsed; while (!cts.Token.IsCancellationRequested) { await Task.Delay(1000, cts.Token); var now = sw.Elapsed; var elapsed = (now - lastTime).TotalSeconds; var currentSent = globalStats.TotalMessagesSent; var currentRecv = globalStats.TotalMessagesReceived; var qpsSend = (currentSent - lastSent) / elapsed; var qpsRecv = (currentRecv - lastRecv) / elapsed; // 计算延迟统计 var latencies = latencyHistogram.ToArray(); var avgLatency = latencies.Length > 0 ? latencies.Average() : 0; var p99Latency = latencies.Length > 0 ? latencies.OrderBy(x => x).Skip((int)(latencies.Length * 0.99)).FirstOrDefault() : 0; Console.WriteLine($"[{now:hh\\:mm\\:ss}] " + $"发送QPS: {qpsSend:N0}/s | 接收QPS: {qpsRecv:N0}/s | " + $"平均延迟: {avgLatency:F2}ms | P99延迟: {p99Latency:F2}ms | " + $"活跃连接: {globalStats.ActiveConnections}"); lastSent = currentSent; lastRecv = currentRecv; lastTime = now; // 清理旧采样 while (latencyHistogram.Count > 100000) latencyHistogram.TryTake(out _); } }, cts.Token); // 定时结束 if (config.DurationSeconds > 0) { _ = Task.Run(async () => { await Task.Delay(config.DurationSeconds * 1000); Console.WriteLine($"\n[时间到] 测试持续 {config.DurationSeconds}s,正在停止..."); cts.Cancel(); }); } try { await Task.WhenAll(testTasks); } catch (OperationCanceledException) { } sw.Stop(); // 输出最终报告 PrintFinalReport(sw, config, clients, globalStats, latencyHistogram); // 断开所有连接 Console.WriteLine("\n[清理] 断开连接..."); await Task.WhenAll(clients.Select(c => c.DisconnectAsync())); Console.WriteLine("[完成]"); } static void PrintFinalReport(Stopwatch sw, BenchmarkConfig config, List<BenchmarkClient> clients, PerformanceStatistics stats, ConcurrentBag<double> latencyHistogram) { Console.WriteLine("\n╔══════════════════════════════════════════════════════════════╗"); Console.WriteLine("║ 压力测试最终报告 ║"); Console.WriteLine("╚══════════════════════════════════════════════════════════════╝"); var totalSeconds = sw.Elapsed.TotalSeconds; var finalLatencies = latencyHistogram.ToArray(); Console.WriteLine($"运行时长: {sw.Elapsed:hh\\:mm\\:ss\\.fff}"); Console.WriteLine($"总连接数: {config.Connections} (成功: {clients.Count(c => c.IsConnected)})"); Console.WriteLine($"总发送消息: {stats.TotalMessagesSent:N0}"); Console.WriteLine($"总接收消息: {stats.TotalMessagesReceived:N0}"); Console.WriteLine($"平均发送QPS: {stats.TotalMessagesSent / totalSeconds:N0}/s"); Console.WriteLine($"平均接收QPS: {stats.TotalMessagesReceived / totalSeconds:N0}/s"); Console.WriteLine($"总发送数据: {stats.TotalBytesSent:N0} bytes ({stats.TotalBytesSent / 1024.0 / 1024:F2} MB)"); Console.WriteLine($"总接收数据: {stats.TotalBytesReceived:N0} bytes ({stats.TotalBytesReceived / 1024.0 / 1024:F2} MB)"); Console.WriteLine($"平均吞吐: {(stats.TotalBytesSent + stats.TotalBytesReceived) / totalSeconds / 1024.0 / 1024:F2} MB/s"); Console.WriteLine($"总错误数: {stats.TotalErrors}"); if (finalLatencies.Length > 0) { Array.Sort(finalLatencies); Console.WriteLine($"\n--- 延迟统计 (样本: {finalLatencies.Length}) ---"); Console.WriteLine($"最小延迟: {finalLatencies[0]:F3}ms"); Console.WriteLine($"平均延迟: {finalLatencies.Average():F3}ms"); Console.WriteLine($"P50延迟: {finalLatencies[finalLatencies.Length / 2]:F3}ms"); Console.WriteLine($"P90延迟: {finalLatencies[(int)(finalLatencies.Length * 0.90)]:F3}ms"); Console.WriteLine($"P99延迟: {finalLatencies[(int)(finalLatencies.Length * 0.99)]:F3}ms"); Console.WriteLine($"P999延迟: {finalLatencies[(int)(finalLatencies.Length * 0.999)]:F3}ms"); Console.WriteLine($"最大延迟: {finalLatencies[^1]:F3}ms"); } } static BenchmarkConfig ParseArgs(string[] args) { var config = new BenchmarkConfig(); for (int i = 0; i < args.Length; i += 2) { if (i + 1 >= args.Length) break; var key = args[i].ToLower(); var value = args[i + 1]; switch (key) { case "-h": case "--host": config.Host = value; break; case "-p": case "--port": config.Port = ushort.Parse(value); break; case "-c": case "--connections": config.Connections = int.Parse(value); break; case "-s": case "--size": config.MessageSize = int.Parse(value); break; case "-d": case "--duration": config.DurationSeconds = int.Parse(value); break; case "-i": case "--interval": config.SendIntervalMs = int.Parse(value); break; case "-b": case "--batch": config.BatchSize = int.Parse(value); break; } } return config; } } public class BenchmarkConfig { public string Host { get; set; } = "127.0.0.1"; public ushort Port { get; set; } = 5555; public int Connections { get; set; } = 1000; public int MessageSize { get; set; } = 256; public int DurationSeconds { get; set; } = 30; public int SendIntervalMs { get; set; } = 0; public int BatchSize { get; set; } = 1; } public class BenchmarkClient { private readonly BenchmarkConfig _config; private readonly PerformanceStatistics _globalStats; private readonly ConcurrentBag<double> _latencyHistogram; private TcpPackClient? _client; private readonly ConcurrentDictionary<uint, Stopwatch> _pendingRequests; private uint _sequence; private byte[]? _sendBuffer; public bool IsConnected { get; private set; } public BenchmarkClient(BenchmarkConfig config, PerformanceStatistics stats, ConcurrentBag<double> latency) { _config = config; _globalStats = stats; _latencyHistogram = latency; _pendingRequests = new ConcurrentDictionary<uint, Stopwatch>(); } public async Task<bool> ConnectAsync() { // 创建 PACK 客户端(非泛型) _client = new TcpPackClient() { PackHeaderFlag = 0x00, //PackHeaderSize = PacketHeader.HeaderSize, MaxPackSize = 65535, SocketBufferSize = 65536, }; // 准备发送缓冲区 _sendBuffer = new byte[PacketHeader.HeaderSize + _config.MessageSize]; var header = PacketHeader.Create((ushort)CommandType.BenchmarkRequest, (uint)_config.MessageSize, 0); MemoryMarshal.Write(_sendBuffer.AsSpan(), ref header); new Random().NextBytes(_sendBuffer.AsSpan(PacketHeader.HeaderSize)); var connectTcs = new TaskCompletionSource<bool>(); _client.OnConnect += (sender) => { IsConnected = true; _globalStats.IncrementConnections(); connectTcs.TrySetResult(true); return HandleResult.Ok; }; _client.OnReceive += (sender, data) => { try { _globalStats.AddBytesReceived(data.Length); if (data.Length >= PacketHeader.HeaderSize) { var respHeader = MemoryMarshal.Read<PacketHeader>(data.AsSpan()); if (_pendingRequests.TryRemove(respHeader.Sequence, out var timer)) { _latencyHistogram.Add(timer.Elapsed.TotalMilliseconds); } _globalStats.IncrementMessagesReceived(); } return HandleResult.Ok; } catch { _globalStats.IncrementErrors(); return HandleResult.Error; } }; _client.OnClose += (sender, operation, errorCode) => { IsConnected = false; _globalStats.DecrementConnections(); connectTcs.TrySetResult(false); return HandleResult.Ok; }; // 启动并连接 if (!_client.Connect(_config.Host, _config.Port)) { return false; } // 等待连接结果或超时 var completed = await Task.WhenAny(connectTcs.Task, Task.Delay(5000)); if (completed != connectTcs.Task) { _client.Stop(); return false; } return connectTcs.Task.Result; } public async Task RunBenchmarkAsync(CancellationToken ct) { if (_client == null || _sendBuffer == null) return; var buffer = new byte[_sendBuffer.Length]; _sendBuffer.CopyTo(buffer, 0); while (!ct.IsCancellationRequested && IsConnected) { try { for (int b = 0; b < _config.BatchSize; b++) { var seq = Interlocked.Increment(ref _sequence); // 更新序列号 var header = PacketHeader.Create( (ushort)CommandType.BenchmarkRequest, (uint)_config.MessageSize, seq); MemoryMarshal.Write(buffer.AsSpan(), ref header); // 记录发送时间 var timer = new Stopwatch(); timer.Start(); _pendingRequests[seq] = timer; if (_client.Send(buffer, 0, buffer.Length)) { _globalStats.IncrementMessagesSent(); _globalStats.AddBytesSent(buffer.Length); } else { _globalStats.IncrementErrors(); _pendingRequests.TryRemove(seq, out _); } } // 控制发送速率 if (_config.SendIntervalMs > 0) { await Task.Delay(_config.SendIntervalMs, ct); } else { // 全速发送时让出时间片 if (_sequence % 1000 == 0) await Task.Yield(); } } catch (OperationCanceledException) { break; } catch (Exception ex) { _globalStats.IncrementErrors(); await Task.Delay(100, ct); } } } public Task DisconnectAsync() { IsConnected = false; _client?.Stop(); return Task.CompletedTask; } }
公用类库 HPSocketTest.Common.dll源码:
// ==================== Common/PacketHeader.cs ==================== using System.Runtime.InteropServices; namespace HPSocketTest.Common; /// <summary> /// 包头结构 (16字节) - PACK 模型自动处理粘包 /// </summary> [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct PacketHeader { public uint Magic; // 魔数 0x48505343 (HPSC) public ushort Version; // 协议版本 public ushort Command; // 命令类型 public uint BodyLength; // 包体长度 public uint Sequence; // 序列号 public const uint MagicValue = 0x48505343; public const int HeaderSize = 16; public static PacketHeader Create(ushort command, uint bodyLength, uint sequence) { return new PacketHeader { Magic = MagicValue, Version = 1, Command = command, BodyLength = bodyLength, Sequence = sequence }; } public bool IsValid => Magic == MagicValue; } /// <summary> /// 命令类型 /// </summary> public enum CommandType : ushort { Heartbeat = 0x0001, EchoRequest = 0x0010, EchoResponse = 0x0011, BenchmarkRequest = 0x0020, BenchmarkResponse = 0x0021, Error = 0x00FF } // ==================== Common/Statistics.cs ==================== namespace HPSocketTest.Common; public class PerformanceStatistics { private long _totalBytesSent; private long _totalBytesReceived; private long _totalMessagesSent; private long _totalMessagesReceived; private long _totalErrors; private long _activeConnections; public long TotalBytesSent => Interlocked.Read(ref _totalBytesSent); public long TotalBytesReceived => Interlocked.Read(ref _totalBytesReceived); public long TotalMessagesSent => Interlocked.Read(ref _totalMessagesSent); public long TotalMessagesReceived => Interlocked.Read(ref _totalMessagesReceived); public long TotalErrors => Interlocked.Read(ref _totalErrors); public long ActiveConnections => Interlocked.Read(ref _activeConnections); public void AddBytesSent(long bytes) => Interlocked.Add(ref _totalBytesSent, bytes); public void AddBytesReceived(long bytes) => Interlocked.Add(ref _totalBytesReceived, bytes); public void IncrementMessagesSent() => Interlocked.Increment(ref _totalMessagesSent); public void IncrementMessagesReceived() => Interlocked.Increment(ref _totalMessagesReceived); public void IncrementErrors() => Interlocked.Increment(ref _totalErrors); public void IncrementConnections() => Interlocked.Increment(ref _activeConnections); public void DecrementConnections() => Interlocked.Decrement(ref _activeConnections); public double GetThroughputMbps() { return (TotalBytesSent + TotalBytesReceived) * 8.0 / 1024 / 1024; } public override string ToString() { return $"[连接数: {ActiveConnections}] [发送: {TotalMessagesSent:N0} msg / {TotalBytesSent:N0} bytes] " + $"[接收: {TotalMessagesReceived:N0} msg / {TotalBytesReceived:N0} bytes] " + $"[错误: {TotalErrors}]"; } }
本例子采用的是PACK模型可自动处理分包粘包。以前繁琐的粘包问题从底层就直接解决了,虽然底层损失了些微性能,但比起java中的Netty框架依然还是强很多。
-----------------------------------------------------------------
- 我做的各种程序们
- 小y的QQ:28657321 (欢迎交流)

浙公网安备 33010602011771号