# 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 持有。