# 用户需求解答 ## 您的需求 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) } ``` **步骤2:Handler中使用** ```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调用 → 数据编码 → 协议编码 → 写入连接 ``` #### 具体实现 **步骤1:Handler写入数据** ```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和struct,Handler直接使用 2. ✅ **自动编码**:服务端自动编码写出的数据 3. ✅ **类型安全**:使用强类型,编译时检查 4. ✅ **简洁**:Handler代码简洁,无需手动解码/编码 5. ✅ **灵活**:支持有帧头和无帧头协议 接下来可以开始实现具体功能。