- SetData 超长时 fmt.Errorf 结果未 return,超 65535 字节静默放行 → 改为返回错误 - ReadFrame 原实现 conn.Read 直读帧头(短读错位)且一次性 bufio.Reader 会丢弃 缓冲中的后续帧字节 → 统一改 io.ReadFull 精确读取,新增连续两帧回归测试 - 补齐单元测试(往返/流水线/超长/Marshal/RawHeader)、examples/frame 例程与 README
51 lines
1.7 KiB
Markdown
51 lines
1.7 KiB
Markdown
# frame
|
|
|
|
应用层帧协议:头 8 字节(版本 1 + 命令 1 + 长度 2 + 流 ID 4,小端序)+ 数据,
|
|
提供帧与 `net.Conn` 间的读写封装,配合 JSON 编解码使用。
|
|
|
|
> 迁移自 go-hua/common/frame.go,独立成包。
|
|
|
|
## 帧格式
|
|
|
|
```
|
|
+---------+---------+-----------+-----------+----------------+
|
|
| ver (1) | cmd (1) | length(2) | sid (4) | data (length) |
|
|
+---------+---------+-----------+-----------+----------------+
|
|
小端序,length 最大 65535
|
|
```
|
|
|
|
## 用法
|
|
|
|
```go
|
|
import (
|
|
"net"
|
|
|
|
"git.zeroonesoft.cn/golib/zogo/frame"
|
|
)
|
|
|
|
// 组帧:版本 + 命令字 + 流 ID,数据可 Marshal 任意 JSON 值
|
|
f := frame.NewFrame(frame.FrameVersion, 0x10, 42)
|
|
f.Marshal(map[string]any{"msg": "hello"})
|
|
|
|
// 连接上写帧 / 读帧(阻塞直到完整帧)
|
|
frame.WriteFrame(conn, f)
|
|
got, err := frame.ReadFrame(conn)
|
|
var data map[string]any
|
|
got.Unmarshal(&data)
|
|
```
|
|
|
|
完整可运行例程:[examples/frame/main.go](../examples/frame/main.go)
|
|
|
|
## 迁移修复(相对 go-hua/common 原实现)
|
|
|
|
1. **SetData 超长未报错**:原实现 `fmt.Errorf` 结果未 return,超长数据静默截断写入;
|
|
现超 65535 字节正确返回错误(有回归测试)。
|
|
2. **ReadFrame 短读/吞字节**:原实现直接 `conn.Read` 读头(TCP 分段会错位),且用
|
|
一次性 `bufio.Reader` 读体(缓冲里多读到的后续帧字节随 reader 丢弃)。现统一改用
|
|
`io.ReadFull` 精确读取,连续多帧不丢数据(有回归测试)。
|
|
|
|
## 注意
|
|
|
|
- 单帧数据上限 65535 字节(length 字段 2 字节),更大 payload 请业务侧分片。
|
|
- `ReadFrame`/`WriteFrame` 非并发安全,同一连接的读与写可各由一个 goroutine 持有。
|