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.

267 lines
6.5 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. **自动解析**服务端能在给定的某种协议下自动解析接收到的数据到header和struct在handler中能够直接使用给定结构的数据。
2. **自动编码**:服务端在写数据到客户端时也能够自动编码数据。
## 设计方案
### 1. 自动解析接收到的数据
**实现方式:** 在服务器接收到数据后自动进行协议解码和数据解码Handler中直接使用解析后的结构体。
#### 数据流程
```
数据到达 → 协议解码 → 数据解码 → Handler直接使用
```
#### 具体实现
**步骤1服务器接收数据**
```go
func (h *eventHandler) OnTraffic(c gnet.Conn) {
// 读取原始数据
rawData, _ := c.Peek(-1)
// 识别协议(根据配置)
protocol := h.getProtocol()
// 协议解码(提取帧头和数据)
header, bodyBytes, err := protocol.Decode(rawData)
// 识别编解码器(根据配置或路由)
codec := h.getCodec()
// 获取请求类型(从路由配置)
requestType := route.RequestType()
// 数据解码(字节 → Go结构体
body := reflect.New(requestType.Elem()).Interface()
codec.Decode(bodyBytes, body)
// 创建Request对象包含已解析的header和body
req := request.New(rawData, protocol)
req.SetHeader(header)
req.SetData(body) // 已解析的结构体
// 创建Context
ctx := context.New(parentCtx, conn, req, resp)
// Handler执行直接使用解析后的数据
handler(ctx)
}
```
**步骤2Handler中使用**
```go
func handler(ctx context.Context) error {
req := ctx.Request()
// 直接使用解析后的结构体(无需手动解码)
loginReq := req.Data().(*LoginRequest)
username := loginReq.Username
password := loginReq.Password
// 读取协议帧头(如果有)
header := req.Header()
if header != nil {
messageType := header.Get("message_type")
}
// 处理业务逻辑...
}
```
### 2. 自动编码写出的数据
**实现方式:** Handler调用`resp.Write()`时,自动进行数据编码和协议封装。
#### 数据流程
```
Handler调用 → 数据编码 → 协议编码 → 写入连接
```
#### 具体实现
**步骤1Handler写入数据**
```go
func handler(ctx context.Context) error {
resp := ctx.Response()
// 直接写入结构体(自动编码)
return resp.Write(LoginResponse{
Code: 200,
Token: "abc123",
})
}
```
**步骤2自动编码流程**
```go
func (resp *responseImpl) Write(data interface{}) error {
// 1. 编解码器编码Go对象 → 字节)
codec := resp.codecRegistry.Default()
bodyBytes, err := codec.Encode(data)
// 2. 协议编码(添加帧头)
header := resp.Header()
frameData, err := resp.protocol.Encode(bodyBytes, header)
// 3. 写入连接
return resp.conn.Write(frameData)
}
```
## 完整示例
### 有帧头协议
```go
// 1. 定义请求和响应类型
type LoginRequest struct {
Username string `json:"username"`
Password string `json:"password"`
}
type LoginResponse struct {
Code int `json:"code"`
Token string `json:"token"`
}
// 2. 注册路由(指定请求类型)
router.RegisterString(
"login",
loginHandler,
router.WithRequestType(&LoginRequest{}),
)
// 3. Handler实现数据已自动解析和编码
func loginHandler(ctx context.Context) error {
req := ctx.Request()
resp := ctx.Response()
// 直接使用解析后的数据(自动解析)
loginReq := req.Data().(*LoginRequest)
// 读取协议帧头(如果有)
header := req.Header()
if header != nil {
messageType := header.Get("message_type")
}
// 处理业务逻辑
token := authenticate(loginReq.Username, loginReq.Password)
// 设置响应帧头(如果有)
resp.Header().Set("message_type", 0x02)
// 写入响应(自动编码)
return resp.Write(LoginResponse{
Code: 200,
Token: token,
})
}
```
### 无帧头协议
```go
// 定义请求和响应类型
type EchoRequest struct {
Message string `json:"message"`
}
type EchoResponse struct {
Message string `json:"message"`
}
// 注册路由
router.RegisterString(
"echo",
echoHandler,
router.WithRequestType(&EchoRequest{}),
)
// Handler实现
func echoHandler(ctx context.Context) error {
req := ctx.Request()
resp := ctx.Response()
// 直接使用解析后的数据(无帧头协议)
echoReq := req.Data().(*EchoRequest)
// 写入响应(自动编码,协议会自动添加\n等分隔符
return resp.Write(EchoResponse{
Message: echoReq.Message,
})
}
```
## 数据流程总结
### 读数据(自动解析)
```
1. Connection.Read() → []byte (原始字节)
2. Protocol.Decode() → FrameHeader + []byte (帧头 + 数据)
3. Codec.Decode() → Go Struct (结构体)
4. Request.SetData(struct) → 设置到Request
5. Handler使用 → req.Data().(*MyStruct) (直接使用)
```
### 写数据(自动编码)
```
1. Handler调用 → resp.Write(struct) (Go对象)
2. Codec.Encode() → []byte (序列化后的数据)
3. Protocol.Encode() → []byte (添加帧头)
4. Connection.Write() → 发送到客户端
```
## 关键特性
1. **自动化**:数据自动解析和编码,无需手动操作
2. **类型安全**:使用强类型,编译时检查
3. **简洁**Handler代码简洁直接使用结构体
4. **灵活**:支持有帧头和无帧头协议
5. **可配置**:通过路由配置指定类型
## 实现状态
### ✅ 已完成
- [x] Context接口更新移除数据读写方法
- [x] Request接口定义支持自动解析
- [x] Response接口定义支持自动编码
- [x] Protocol接口更新支持FrameHeader
- [x] 设计文档
### 🚧 待实现
- [ ] Request和Response的具体实现
- [ ] 服务器自动解析逻辑
- [ ] 路由配置支持指定请求类型
- [ ] 协议实现更新
- [ ] 服务器代码更新
## 总结
新的设计完全满足您的需求:
1.**自动解析**服务端自动解析数据到header和structHandler直接使用
2.**自动编码**:服务端自动编码写出的数据
3.**类型安全**:使用强类型,编译时检查
4.**简洁**Handler代码简洁无需手动解码/编码
5.**灵活**:支持有帧头和无帧头协议
接下来可以开始实现具体功能。