You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
5.0 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 数据流程分析 - 当前实现状态
## 问题解答
### 1. 读数据流程
**你期望的流程:**
```
read bytes -> protocol decode (data bytes) -> codec decode (go struct 或其它结构)
```
**当前实际实现:**
```
read bytes -> SetRequest(raw bytes) -> 路由匹配 -> 处理器
```
**问题:** ❌ **当前实现中没有进行protocol decode和codec decode**
数据是**原始字节直接传递给处理器**,没有经过任何解码。
### 2. 写数据流程
**你期望的流程:**
```
write any or bytes -> codec encode (bytes) -> protocol encode (bytes)
```
**当前实际实现:**
```go
WriteAny(go struct) -> codec.Encode(data) -> protocol.Encode(encodedData) (可选) -> Write(bytes)
```
**结论:** ✅ **写数据流程是正确的!**
流程是:
1. Go对象struct/map等
2. 编解码器编码codec.Encode→ 字节数组
3. 协议编码protocol.Encode可选→ 包含协议帧头的字节数组
4. 写入连接Write
### 3. 完整的数据流程(当前状态)
#### 写数据流程 ✅
```
处理器中:
ctx.WriteAny(struct{...})
codec.Encode(struct) → []byte (JSON/Binary/Protobuf等)
protocol.Encode([]byte) → []byte (包含Magic、长度、校验和等可选)
conn.Write([]byte) → 客户端
```
#### 读数据流程 ❌ (未实现)
```
客户端 → conn.Read() → []byte (原始字节)
SetRequest([]byte) → ctx.Request() (仍然是原始字节)
路由匹配 → 处理器
处理器中直接使用 ctx.Request() (原始字节,未解码)
```
**问题:** 读数据时没有进行:
- ❌ protocol decode去除协议帧头
- ❌ codec decode将字节解码为Go对象
### 4. 自定义协议帧头问题
**你的问题:**
> 如果我需要在 write 时写入一些自定义协议帧头数据呢或者在write之前写入呢该怎么办
**当前限制:**
1. **协议编码是自动的:** 如果启用`EnableProtocolEncode`,协议编码会自动在`WriteAny`中执行,无法手动控制
2. **无法在协议帧头之前写入数据:** 当前没有API支持在协议编码之前或之后写入额外的自定义数据
3. **无法自定义协议帧头格式:** 协议帧头格式由协议实现决定如nnet协议的Magic、长度、校验和无法自定义
**解决方案:**
#### 方案1直接使用 Write 方法(绕过自动编码)
```go
// 手动构建完整的协议帧
func handler(ctx ctxpkg.Context) error {
// 1. 准备数据
data := []byte("your data")
// 2. 手动添加自定义协议帧头
header := []byte("CUSTOM_HEADER")
frame := append(header, data...)
// 3. 直接写入绕过codec和protocol编码
return ctx.Write(frame)
}
```
#### 方案2在协议编码后追加数据
```go
func handler(ctx ctxpkg.Context) error {
// 1. 使用WriteAny自动编码
resp := Response{Code: 200}
ctx.WriteAny(resp) // 自动进行codec encode和protocol encode
// 2. 追加自定义数据
customData := []byte("custom footer")
ctx.Write(customData)
return nil
}
```
#### 方案3自定义协议实现
```go
// 实现自定义协议在Encode方法中添加自定义帧头
type CustomProtocol struct {
// ...
}
func (p *CustomProtocol) Encode(data []byte) ([]byte, error) {
// 添加自定义协议帧头
header := []byte("CUSTOM_HEADER")
// ... 其他协议帧头字段
return append(header, data...), nil
}
```
## 需要实现的功能
### 1. 读数据解码支持
需要实现:
- ✅ protocol decode去除协议帧头提取数据部分
- ✅ codec decode将字节解码为Go对象
**建议的读数据流程:**
```
read bytes → protocol.Decode(bytes) → data bytes → codec.Decode(data bytes) → go struct
```
### 2. 写数据增强
需要支持:
- ✅ 在协议编码之前写入自定义数据
- ✅ 在协议编码之后写入自定义数据
- ✅ 自定义协议帧头格式
**建议的API**
```go
// 在协议编码之前写入
ctx.WriteBeforeProtocol(data []byte) error
// 在协议编码之后写入
ctx.WriteAfterProtocol(data []byte) error
// 写入自定义协议帧头
ctx.WriteHeader(header []byte) error
```
## 当前实现总结
### ✅ 已实现
1. **写数据编码:** codec encode → protocol encode (可选)
2. **自动编解码器匹配:** 根据配置自动选择编解码器
3. **协议层编码:** 支持协议层编码如nnet协议
### ❌ 未实现
1. **读数据解码:** 没有protocol decode和codec decode
2. **自定义协议帧头:** 无法灵活控制协议帧头的写入
3. **解码后的请求数据:** 处理器无法直接获取解码后的Go对象
## 建议
1. **实现读数据解码:** 在`OnTraffic`或路由匹配之前先进行protocol decode和codec decode
2. **增强Context API** 添加`WriteHeader`、`WriteBeforeProtocol`、`WriteAfterProtocol`等方法
3. **支持解码后的请求数据:** 添加`DecodedRequest()`方法返回解码后的Go对象