简介HPSocket.Net 开发资源包是一份面向 .NET 平台、使用 C# 语言进行 TCP Socket 网络编程的完整示例集合特别适合需要处理高并发、多线程和异步通信的服务端或桌面端开发者。压缩包内共有 662 个文件整体大小约 918KB其中包含 329 个 C# 源码文件以及 config、csproj、settings、resx 等工程配置还有证书、密钥和 bat 启动脚本能够支持从编译调试到安全通信验证的完整流程。目前已有 457 人学习/下载适合初学者对照模板理解创建 Socket、连接服务器端口、发送数据、接收数据、关闭连接等完整过程也适合进阶者研究并发连接管理、异常处理和连接复用等常见问题。示例还展现了 HPSocket.Net 针对异步操作、多线程并发和消息模板的封装思路便于减少 TCP 开发中的粘包处理、数据序列化和手动重试等重复工作。边阅读源码边运行验证能帮助开发者快速掌握稳定的网络通信实现并将其迁移到实际项目当中对自研通信组件或集成现有系统均有直接参考价值。1. 拿到 HPSocket.Net 之后先搞清它到底替你省了哪些事做 C# 网络通信的人八成都有过被原生 Socket 折磨的经历连接管理要自己写、粘包拆包要自己算、断线重连要自己扛好不容易跑起来一压并发就崩。HPSocket.Net 就是冲着这些痛点来的——它是 HPSocket 高性能通信组件的 .NET 封装版底层用 C 实现上层给 C# 开发者暴露了一套相对友好的 API。这个包里有服务端和客户端的一键启动脚本还带了 server2.cer 和 client2.cer 证书文件说明它连 TCP 通信中最麻烦的 SSL/TLS 加密通道都给你留好了现成入口。适合谁用写过几天 Socket、被半包粘包和异步回调搞到头秃的后端开发者以及需要在 Winform、WPF 或者服务端项目里快速落地稳定 TCP 通信的人。下面直接把整个包的用法、参数和坑一条条拆开说。2. 从原生 Socket 到 HPSocket同样是 TCP差别在哪2.1 先温习原生 Socket 的五步套路C# 里用 Socket 类走 TCP 的基本流程摘要里已经列得很清楚这里结合代码说明为什么这套写法只适合入门、不适合生产。// 1. 创建 Socket 对象IPv4 地址族、流式套接字、TCP 协议 Socket socket new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 2. 连接服务器 socket.Connect(new IPEndPoint(IPAddress.Parse(127.0.0.1), 8080)); // 3. 发送数据 byte[] msg Encoding.UTF8.GetBytes(hello server); socket.Send(msg); // 4. 接收数据 byte[] buffer new byte[1024]; int received socket.Receive(buffer); string data Encoding.UTF8.GetString(buffer, 0, received); // 5. 关闭连接 socket.Shutdown(SocketShutdown.Both); socket.Close();这段代码每一步对应 TCP 协议栈的一个动作Connect触发三次握手Send把应用层数据交给协议栈打包成报文段Receive阻塞等待对端数据。参数上有两个值得注意的地方AddressFamily.InterNetwork表示只走 IPv4如果你要支持 IPv6 得改成InterNetworkV6SocketType.Stream对应 TCP 的字节流特性ProtocolType.Tcp是传输层协议选择。buffer大小直接决定了单次Receive能拿到多少字节设成 1024 只是教学演示真做项目至少要 4096 起步。但这套写法有个致命问题同步阻塞。Receive没数据就卡住线程一个连接占一个线程1000 个连接就是 1000 个线程线程切换开销能把服务器拖垮。而且Send和Receive之间没有协议层封装你发出去的字节流对端怎么切分这就是万恶的粘包问题。2.2 HPSocket 解决的核心矛盾连接管理与人手分配HPSocket 的底层模型和原生 Socket 有本质区别。它内部用完成端口IOCP处理高并发连接线程池按 CPU 核心数动态伸缩不用一个连接一个线程。对 .NET 开发者来说你不再直接操作Socket对象而是通过事件回调处理连接建立、数据到达、连接关闭。using HPSocket; // 创建 TCP 服务端 ITcpServer server new TcpServer(); server.OnAccept (connId, clientIp, clientPort) { Console.WriteLine($客户端连接: {connId} from {clientIp}:{clientPort}); return true; // 返回 true 表示接受该连接 }; server.OnReceive (connId, bytes) { string msg Encoding.UTF8.GetString(bytes); Console.WriteLine($收到数据: {msg}长度: {bytes.Length}); // 处理完记得把数据回写或保存 return true; }; // 监听本地 8080 端口 bool ok server.Start(new IPEndPoint(IPAddress.Any, 8080));这段代码有三层信息。第一OnAccept回调里你拿到了connId这是 HPSocket 给每个连接分配的唯一标识后续发消息、断连都靠它定位连接不用自己维护 Socket 对象字典。第二OnReceive回调里的bytes已经是 HPSocket 帮你按连接隔离好的数据块不再需要从同一个 Socket 上抢夺数据。第三Start方法的IPEndPoint参数和原生 Socket 的Connect参数语义一样但底层走的监听逻辑完全不同。这就是 HPSocket 的第一个价值把连接生命周期管理从你的业务代码里剥出去。你的业务只需要关注数据到了我怎么处理不需要关心这个连接什么时候断、断了怎么清资源、下一个连接谁来接。2.3 数据模板与粘包拆包二进制协议的正确打开方式原生 Socket 最大的坑就是粘包。TCP 是字节流协议没有消息边界你 Send 两次 ABC 和 DEF对端可能一次 Receive 就拿到 ABCDEF。HPSocket 提供了一套数据模板Data Template机制允许你定义包头结构让组件自动拆包。// 定义包头4 字节包头表示消息体长度 ITcpServer server new TcpServer(); server.DataReceiveMode DataReceiveMode.None; // 关闭内置拆包手动处理 // 或者用固定包头模式前 4 字节存长度 byte[] header new byte[4]; int bodyLength BitConverter.ToInt32(header, 0);HPSocket 支持两种常用拆包策略固定包头比如前 4 字节写长度和结束符模式比如以\r\n结尾。设置对应参数后OnReceive里拿到的bytes就是一个完整的包不会再出现半个包或者粘包。这一点对新手来说是质变——你不用再自己写累积缓冲区、解析半包状态的代码了。3. 把 server.bat 和证书文件用起来一条带上 SSL 的完整链路3.1 批处理脚本里藏着什么这个压缩包里有server.bat和client.bat说明作者预编译好了对应的启动命令。bat 的核心作用就是省去你手动敲命令的麻烦但你要知道里面大致做了什么echo off :: 启动服务端监听 0.0.0.0:8080启用 SSL HPSocket.Server.exe -p 8080 -c server2.cer -k server2.key :: 启动客户端连接本机 8080携带客户端证书 HPSocket.Client.exe -h 127.0.0.1 -p 8080 -c client2.cer -k client2.key参数含义分别是-p指定端口-c指定证书文件路径-k指定私钥文件路径-h指定服务端地址。证书文件是 PEM 格式的server2.cer 对应服务端公钥证书和私钥client2.cer 对应客户端证书。注意server2.cer在包里出现了多次实际检查时应该只有一个文件重复列出可能是打包工具的问题不影响使用。3.2 SSL 握手过程与 .NET 侧的验证逻辑为什么 TCP 通信要上证书因为明文 TCP 传输的数据在链路上等同于裸奔抓包工具一抓一个准。SSL/TLS 做的事情是在 TCP 之上再加一层加密隧道而证书是让双方确认彼此身份的凭证。在 HPSocket 的 .NET 封装里启用 SSL 只需要在服务端和客户端配置证书参数// 服务端启用 SSL ITcpServer server new TcpServer(); server.SslConfig new SslConfig { PemCertFile server2.cer, PemKeyFile server2.key, VerifyMode SslVerifyMode.Peer, // 双向验证 }; // 客户端启用 SSL ITcpClient client new TcpClient(); client.SslConfig new SslConfig { PemCertFile client2.cer, PemKeyFile client2.key, VerifyMode SslVerifyMode.Peer, ServerName localhost // 如果证书 CN 是域名这里要填对应的域名 }; bool connected client.Connect(127.0.0.1, 8080);这里有个容易踩的坑VerifyMode设为Peer表示双向验证服务端要验证客户端证书客户端也要验证服务端证书如果只用服务端证书单向验证客户端那边就不需要配置证书服务端的VerifyMode改成None即可。ServerName参数在证书校验阶段会被用来比对证书的 CN通用名称或 SAN主题备用名称如果证书里写的是localhost而你连的是192.168.1.10校验会失败。3.3 证书生成没有现成证书时自己造一个包里带了证书不代表项目里能直接用生产环境一般要换成自己的证书。自签名证书可以用openssl生成:: 生成服务端私钥和自签名证书 openssl req -x509 -newkey rsa:2048 -keyout server2.key -out server2.cer -days 365 -nodes -subj /CNlocalhost :: 生成客户端私钥和自签名证书 openssl req -x509 -newkey rsa:2048 -keyout client2.key -out client2.cer -days 365 -nodes -subj /CNclient-nodes参数表示私钥不加密存储测试环境方便生产环境千万别这么干-subj里的 CN 字段决定了证书属于谁服务端的 CN 会被客户端用来做域名校验。生成的server2.key是私钥文件绝对不要泄露.cer是公钥证书可以分发。4. 服务端与客户端完整实战从连接到双向收发4.1 服务端核心逻辑连接池、多线程与回写把上一章的碎片拼起来一个能用的 HPSocket TCP 服务端长这样using HPSocket; using System.Net; public class TcpServerDemo { private ITcpServer _server; public void Start(int port) { _server new TcpServer(); // 连接事件拿到连接 ID 和客户端地址 _server.OnAccept (connId, clientIp, clientPort) { Console.WriteLine($[连接] {connId} - {clientIp}:{clientPort}); return true; }; // 接收事件data 已经是按你的拆包配置处理好后的完整包 _server.OnReceive (connId, data) { string msg Encoding.UTF8.GetString(data); Console.WriteLine($[收包] {connId}: {msg}); // 回写把原数据加个前缀返回给客户端 byte[] resp Encoding.UTF8.GetBytes($[echo] {msg}); _server.Send(connId, resp, resp.Length); return true; }; // 断开事件清理连接 ID 对应的业务数据 _server.OnClose (connId, socketError) { Console.WriteLine($[断开] {connId}, 错误码: {socketError}); }; // 启动监听 bool ok _server.Start(new IPEndPoint(IPAddress.Any, port)); Console.WriteLine($服务端启动: {ok}, 端口: {port}); } public void Stop() { _server?.Stop(); } }OnReceive回调返回值true告诉 HPSocket 数据已经处理完毕可以释放缓冲区返回false会导致数据被重新放回接收队列形成死循环。Send方法的第三个参数是数据长度如果你传的 byte[] 是用Encoding.UTF8.GetBytes生成的长度就是data.Length注意别用resp数组的容量值。这个服务端在 HPSocket 内部是多线程模型你可以在回调里做耗时操作但要注意临界资源的锁保护——比如多个连接同时写同一个文件不加锁必然出乱子。4.2 客户端逻辑连接复用与消息发送客户端相对简单但要理解连接复用的概念using HPSocket; public class TcpClientDemo { private ITcpClient _client; public void Connect(string host, int port) { _client new TcpClient(); _client.OnConnect (connId) { Console.WriteLine($连接成功: {connId}); // 连接建立后立即发送一条验证消息 byte[] msg Encoding.UTF8.GetBytes({\type\:\hello\,\ts\:1735689600}); _client.Send(msg, msg.Length); return true; }; _client.OnReceive (connId, data) { Console.WriteLine($服务端响应: {Encoding.UTF8.GetString(data)}); return true; }; _client.OnClose (connId, socketError) { Console.WriteLine($连接断开: {socketError}); }; bool ok _client.Connect(host, port); Console.WriteLine($连接结果: {ok}); } public void SendMessage(string text) { if (_client null || !_client.IsConnected) return; byte[] data Encoding.UTF8.GetBytes(text); _client.Send(data, data.Length); } }OnConnect事件是判断连接是否成功的唯一可靠途径Connect方法返回的bool只代表连接请求是否发出不代表握手完成。客户端在断线后如果想重连不能直接复用原来的_client对象需要重新new一个TcpClient再Connect这是 HPSocket 的一个设计约束——连接对象绑定了一次完整的生命周期。Send方法在多线程环境下是线程安全的你可以在业务线程里直接调用不用额外加锁。4.3 数据包格式设计JSON 还是自定义二进制HPSocket 只负责传输不替你做业务协议设计。你在OnReceive里拿到byte[]之后怎么解析完全是自己的事。常见做法有两种一是传 JSON 字符串。在OnReceive里用Encoding.UTF8.GetString转字符串再用System.Text.Json.JsonSerializer.Deserialize解析成对象。方便调试但每包数据都要经过字符串转对象的过程性能和内存占用不如二进制。二是二进制协议包头固定 4 字节表示消息体长度后面跟消息体消息体内部再用字段偏移或 TLV 结构解析。这种方案性能高、包体积小适合网关采集、高频交易等场景。我的建议是测试阶段用 JSON业务稳定后压测一把再决定要不要切二进制。5. 避坑指南HPSocket 实战中四个高频翻车点5.1 证书校验失败现象是连接建立后立刻被断开现象客户端Connect返回true但OnConnect回调不触发几毫秒后OnClose被调用错误码显示 SSL 握手失败。服务端日志里能看到 TLS alert 记录。原因服务端证书的 CN 或 SAN 与客户端SslConfig.ServerName不匹配。证书里写的是localhost客户端连的是127.0.0.1一致性校验过不去或者客户端没设ServerName走了默认空值。解决两种情况任选一种。统一用localhost作为连接地址或者重新生成证书把-subj里的 CN 改成实际部署的 IP 或域名。测试环境最省事的办法是服务端把VerifyMode设为None客户端把VerifyMode置为None只做加密不做身份校验能快速排除问题点。5.2 粘包拆包后数据还是不对OnReceive 拿到的是多包拼接现象客户端连续快速 Send 了 10 条消息服务端OnReceive一次触发了 3 次每次拿到的数据长度各不相同有些是一条完整消息有些是两条拼在一起。原因服务端没配置拆包模式HPSocket 默认把DataReceiveMode设为把 TCP 流原始交给回调所以依然会有粘包。解决设置server.DataReceiveMode DataReceiveMode.FixedHead并指定包头结构server.DataReceiveMode DataReceiveMode.FixedHead; server.FixedHeadSize 4; // 这时 HPSocket 会读取前 4 字节当作包体长度然后自动把包体拆出来再触发 OnReceive注意FixedHeadSize设为 4 意味着客户端发送的每条消息前 4 个字节必须是大端或小端序的整数表示后续消息体长度。你需要在客户端Send之前手动拼上长度头byte[] body Encoding.UTF8.GetBytes(hello); byte[] packet new byte[4 body.Length]; BitConverter.GetBytes(body.Length).CopyTo(packet, 0); body.CopyTo(packet, 4); _client.Send(packet, packet.Length);如果嫌手动拼包头麻烦可以把DataReceiveMode换成Terminator模式约定用\r\n结尾HPSocket 会在收到完整结束符后才触发OnReceive。5.3 服务端重启后连接不释放TIME_WAIT 堆积现象开发调试时反复重启服务端过一阵子客户端连接报错socket is not相关异常服务端端口被占用netstat看到大量TIME_WAIT状态的连接。原因TCP 四次挥手后主动关闭方会进入TIME_WAIT状态持续 2 个 MSL最长报文段寿命通常是 2 分钟。服务端频繁崩溃重启时旧的连接还没完全释放新监听就撞上了。解决开发环境在服务端Start之前设置地址重用server.ReuseAddress true;这个属性对应底层SO_REUSEADDR套接字选项允许 TIME_WAIT 状态下的端口被立即重新绑定。生产环境不要乱开会掩盖一些连接异常释放的问题。5.4 发送大数据时内存暴涨Send 回调的缓冲区没有及时释放现象客户端每秒发送 100 个 1MB 的包服务端内存以肉眼可见的速度上涨最后 OOM。原因OnReceive回调里处理数据耗时过长HPSocket 的接收缓冲区来不及释放新的数据又进来了队列堆积。解决两个方向。一是回调里不要做重计算把数据封装后丢给后台队列比如ChannelT或BlockingCollectionT立即返回true释放缓冲区二是控制OnReceive的处理速度必要时给服务端加背压机制比如当待处理队列长度超过阈值时回调返回false让底层暂停接收。后者慎用返回false可能导致数据重传风暴。6. 把连接风暴跑起来用 .bat 脚本和 500 个并发连接给服务端做体检这个资源里的server.bat和client.bat最适合用来验证一件事HPSocket 在高并发场景下的真实吞吐。我的习惯是按下述流程做连接风暴测试——不需要写复杂的压测工具一条 PowerShell 循环就能凑够连接数。# 启动服务端 Start-Process -FilePath cmd.exe -ArgumentList /c server.bat # 循环创建 500 个客户端连接假设 client.bat 支持命令行参数传连接名 1..500 | ForEach-Object { Start-Process -FilePath cmd.exe -ArgumentList /c client.bat -n Client_$_ } # 查看连接数 netstat -an | Select-String :8080 | Measure-Object这个测试要观察三个指标第一netstat里 ESTABLISHED 状态的数量是否稳定在 500第二服务端日志里有没有连接被拒绝的记录第三内存占用是否线性增长。HPSocket 用 IOCP 模型理论上前 1000 个连接的内存增长非常平缓如果你看到抛物线式的内存上涨问题大概率出在业务回调而不是组件本身。再进一步可以让每个客户端连接后每 3 秒发一条心跳消息服务端收到后回一句pong用这个循环验证双向通信的稳定性跑 30 分钟看有没有断线漏包。从那以后我每次集成 HPSocket 到新项目都会强制走一遍这个连接风暴流程——证书验一遍、粘包拆包验一遍、连接释放验一遍三关过了才敢接业务。这套流程不光验组件更是在验自己对连接生命周期和数据边界的理解有没有漏洞希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
高通Android音频架构:从FE/BE到ADSP的完整链路 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/28 1:27:48
ESP32-S3烧录失败根源:GPIO0与RST时序协同机制解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/28 1:27:48
电子信息工程四年规划:嵌入式与芯片方向学习路线 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/28 1:27:42
Spingboot启动预热的实现 启动预热的适用场景启动预热适合以下情况:数据主要来自第三方接口,无法直接从本地数据库读取。第三方接口响应较慢,首次访问容易超时。一个页面需要调用多个第三方接口或逐项查询。数据读取频繁,但变化不频繁。希望服务启动后&… · 2026/9/28 3:40:12
学Java别走弯路,这5个方向最吃香 学Java的人很多,但学明白的人不多。有人学了半年还在写控制台程序,有人一年就能独当一面。差别不在天赋,而在方向。Java生态太庞大了,什么都学等于什么都没学。选对方向,事半功倍。今天盘点当前最吃香的5个Java方向&am… · 2026/9/28 3:32:15
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01
制作网页比较方便的软件怎么选?一文搞懂避坑指南 制作网页比较方便的软件怎么选?一文搞懂避坑指南 很多老板一上来就问:做个网站多少钱?但我反问他:你的域名买了吗?服务器租了吗?他一脸懵。这就是典型的“域名服务器搞不懂”。别急,今天咱们不聊虚的,直接 一文搞懂 那些让你头秃的技术名词。… · 2026/9/28 0:00:06
婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量 婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量 找婚恋网站建站公司,最怕的就是被坑高价。很多同行跟我吐槽,报价单上写得模棱两可,功能栏里全是“高级定制”、“专属UI”,结果落地全是套壳。今天不聊虚的,直接甩几个我经手的 实战案例… · 2026/9/28 0:00:19
济南做网站多少钱:3个案例拆解,防黑源码下载全攻略 济南做网站多少钱:3个案例拆解,防黑源码下载全攻略 上周济南一个做建材的老板找我,脸都绿了。他的官网首页弹出了赌博广告,后台被植入了挖矿脚本。他慌得问我:“网站被黑挂马不知道怎么办?能不能直接找之前的外包公司要源码下载,看看哪里被动了手脚?… · 2026/9/28 0:00:25