网络通讯
使用网络通讯组件时理解 TCP 分包、处理器生命周期和资源所有权。
Zongsoft.Net 提供基于 TCP 的客户端、服务器、通道与分包器,也包含 FTP 文件系统接入。它适合设备通讯或已有二进制协议接入;如果需求是跨服务的持久消息和消费确认,应先阅读消息队列。
TCP 为什么需要分包
TCP 提供有序字节流。发送端一次写入的内容,接收端可能分多次读到;多次写入也可能合并为一次读取。因此,“读到一段字节”不能直接等同于“收到一条业务消息”。
分包器负责把字节流还原为协议包。双方必须约定同一种格式,并对长度、编码和内容进行检查。
Headed
使用四字节大端长度头划分包
对端也使用相同长度头协议
Headless
按当前可读数据交付内容
上层自己解析边界,或协议本来就是流
不要把 Headless 用作“省略长度头但仍每次收到完整消息”的捷径。对于文本行协议,应处理跨读取的半行、多行、最大长度以及断连前未结束的行。
客户端与服务器如何配合
客户端配置目标地址和接收处理器,通过 ConnectAsync 建立连接;发送路径也可按实现延迟连接。服务器监听端点后为连接建立通道,将解出的包交给处理器。业务处理与网络读取是不同职责:分包器不负责认证、业务路由或重试。
仓库提供 TcpClient.Headed 和 TcpClient.Headless 共享入口。它们的地址、处理器及连接状态是共享可变状态,适合受控的单连接场景;不要让多个业务模块各自改写同一个入口的配置。
💡 自定义客户端时既要选择接收分包器,也要核对发送通道是否正确打包。内置 Headed 客户端专门覆盖了原始字节发送路径,不能仅给通用客户端传入一个分包器就推断所有发送重载都会自动添加长度头。
内存与生命周期
有头模式交付的 System.Buffers.ReadOnlySequence<byte> 可能引用管道缓冲区,应在处理器调用期间完成读取。如果需要放入后台队列或长时间保存,先复制有效内容。
无头模式使用 System.Buffers.IMemoryOwner<byte> 表达缓冲区所有权。框架通道在处理完成后释放所交付的资源;处理器不得在返回后继续访问其内存。编写自定义通道或处理器时,需要明确哪一层释放缓冲区,避免重复释放或悬挂引用。
连接关闭、应用停止和业务取消也应分别处理。当前 ConnectAsync 不接受取消令牌;不能把发送或断连方法上的取消参数理解为连接建立的统一取消机制。
可观察结果与业务确认
发送完成通常表示数据已经交给本地传输路径,广播返回的数量表示本地成功发送的连接数。它们都不是对端业务已经处理的证明。需要业务确认时,应在协议中加入请求标识、响应、超时和重复请求处理。
建议至少记录连接建立/关闭原因、收发字节量、解包失败及处理耗时;不要在普通日志中完整记录敏感报文。对于暴露在不可信网络上的监听端口,还需要应用明确连接认证、包大小限制和资源配额。
验证路径
先使用仓库的网络示例,在两个进程中以环回地址验证服务端和客户端;默认示例端口为 7969。随后加入拆分写入、连续多包、异常长度和断连重连测试,确认协议边界再接入真实设备。
部署 .plugin 会注册相关扩展,例如 FTP 文件系统;它不会自动替业务启动一个 TCP 监听器。启动/停止监听应由宿主生命周期中的工作器或明确的业务入口承担。
源码入口:网络组件。
最后更新于