2026-06-09 分包协议 7 项优化修复
变更概述
对 cPacketProtocol 和 cWinSock 的分包协议实现进行全面审查,修复 2 个 Bug、1 个安全风险、1 个逻辑缺陷、3 个设计问题。
修复详情
1. 心跳绕过协议编码(严重 Bug)
问题:心跳数据通过 m_oSocket.SendArray baHB 直接发送原始字节,未经 Encode 编码。但接收端统一走 Decode 解码。若心跳帧恰好在正常消息碎片中间到达,会导致协议状态机混乱(如 ppLengthHeader 误将心跳字节当成长度头解析)。
修复:cWinSock.cls 心跳发送改为 Me.SendData baHB,确保心跳数据经过协议编码,收发两端一致。
2. 2 字节长度头 Encode 溢出(严重 Bug)
问题:VB6 的 Integer 是有符号的(-32768~32767),2 字节头实际能表示 0~65535。当 lDataLen > 32767 时,CInt(lDataLen) 抛出运行时错误。
修复:cPacketProtocol.cls Encode 方法:
- 增加
lDataLen > 65535校验,超限直接ERR.Raise lDataLen > 32767时映射到lDataLen - 65536写入 Integer- 大端模式使用
lDataLen(Long)计算而非nLen(Integer)
3. 大端 4 字节解析溢出(Bug)
问题:ParseLengthHeader 中大端 4 字节解析 m_baRecvBuffer(0) * &H1000000,当首字节 >= 128 时结果符号位为 1,变成负数。
修复:改用 (m_baRecvBuffer(0) And &H7F) * &H1000000 取低 7 位,再用 Or &H80000000 恢复最高位。
4. 缺少最大包/缓冲区限制(安全风险)
问题:原实现中最大包限制 10MB 硬编码、不可配置,非法长度时静默丢弃缓冲区无通知,缓冲区累积无上限(攻击者可发大量不完整包耗尽内存)。
修复:cPacketProtocol.cls 新增:
MaxPacketSize属性(默认 1MB)— 单包最大大小,超限报错丢弃MaxBufferSize属性(默认 4MB)— 缓冲区累积上限,防内存耗尽ExtractLengthHeaderMessages中用MaxPacketSize替代硬编码 10MBDecode合并缓冲区前检查MaxBufferSize- 超限时抛出明确错误信息而非静默丢弃
cWinSock.cls 新增 MaxPacketSize/MaxBufferSize 代理属性,TCP/UDP 客户端自动继承。
5. UDP 跳过分包协议(功能缺失)
问题:UDP 模式下收到的数据完全不走 cPacketProtocol.Decode,用户设置了 PacketProtocol 也不会生效。
修复:cWinSock.cls m_oSocket_OnReceive 中 UDP 分支:
- UDP 客户端创建时继承服务端的协议配置(含 MaxPacketSize/MaxBufferSize)
- 收到数据报后检查客户端是否启用协议,若启用则
Decode后触发MessageArrival - 无协议时保持原有
UserData+DataArrival路径
6. FixedLength 静默截断(设计问题)
问题:数据超长时直接截断,不报错也不通知,调用方无法知道数据被裁剪。
修复:数据超长时直接 ERR.Raise 报错,不再静默截断。
7. MessageArrival + DataArrival 双触发(易用性问题)
问题:分包模式下每条完整消息同时触发两个事件。如果用户同时监听两个事件并都调用 GetData,第二次调用会拿到空数据。
修复:协议模式下只触发 MessageArrival,移除了 DataArrival 的兼容触发。无协议模式下仍触发 DataArrival(向后兼容)。事件注释已更新说明。
修改文件
cPacketProtocol.cls
| 改动 | 位置 |
|---|---|
新增 m_lMaxPacketSize / m_lMaxBufferSize 成员变量 | 声明区 |
新增 MaxPacketSize / MaxBufferSize 属性 | Properties 区 |
Class_Initialize 初始化默认值(1MB / 4MB) | Initialize |
Encode ppLengthHeader 增加溢出校验和 Integer 映射 | Encode 方法 |
Encode ppFixedLength 超长改为报错 | Encode 方法 |
ParseLengthHeader 大端 4 字节无符号解析 | ParseLengthHeader |
ExtractLengthHeaderMessages 用 MaxPacketSize 替代硬编码 + 报错 | ExtractLengthHeaderMessages |
Decode 合并缓冲区前检查 MaxBufferSize | Decode 方法 |
cWinSock.cls
| 改动 | 位置 |
|---|---|
新增 MaxPacketSize / MaxBufferSize 代理属性 | Properties 区 |
MessageArrival 事件注释更新 | 事件声明 |
心跳发送改为 Me.SendData baHB | m_oHeartbeat_Tick |
| TCP OnAccept 客户端继承 MaxPacketSize/MaxBufferSize | m_oSocket_OnAccept |
| UDP 分支支持协议解码 + 继承配置 | m_oSocket_OnReceive |
| 协议模式移除 DataArrival 双触发 | m_oSocket_OnReceive |
设计.md
新增"分包协议设计要点"章节,记录协议类型、安全限制属性、事件模型、心跳一致性、UDP 支持等设计决策。