优化websocket parser解包正确
author孙春阳 <snickersun@163.com>
Wed, 13 Aug 2025 21:23:13 +0000 (05:23 +0800)
committer孙春阳 <snickersun@163.com>
Wed, 13 Aug 2025 21:23:13 +0000 (05:23 +0800)
code/sdk/drivers/peripheral/slip/cat1Service/cat1_ai_server.cpp
code/sdk/drivers/peripheral/slip/cat1Service/cat1_ws.cpp
code/sdk/drivers/peripheral/slip/cat1Service/websocket_parser.cpp
code/sdk/drivers/peripheral/slip/tcpmanager/tcp_simple_manager.c
test_ws_parser/Makefile [new file with mode: 0644]
test_ws_parser/websocket_analysis.py [new file with mode: 0644]
test_ws_parser/websocket_frames_analysis.json [new file with mode: 0644]
test_ws_parser/websocket_parser_standalone.cpp [new file with mode: 0644]
test_ws_parser/websocket_simple_analysis.json [new file with mode: 0644]
test_ws_parser/websocket_simple_analysis.py [new file with mode: 0644]

index 7685fd3..e1aeb4c 100644 (file)
@@ -440,7 +440,6 @@ static int ws_queue_put(ws_message_queue_t* queue, const uint8_t* data, uint16_t
     item->type = type;
     item->timestamp = osKernelGetTickCount();
     item->in_use = true;
-    printf("ws_queue_put type %d , length %d , data %s\n",type,item->length,item->data);
     
     queue->tail = (queue->tail + 1) % WS_QUEUE_SIZE;
     queue->count++;
@@ -950,14 +949,16 @@ void bk_websocket_demo(void *data) {
                 chat_client = init_websocket_client(url_buf, NULL, 1);
                 if (chat_client != NULL) {
                     chat_client->msg_queue = &chat_msg_queue;   
-                    chat_client->packet_callback = chat_on_ws_packet_callback;
+                    ws_set_packet_callback(chat_client, chat_on_ws_packet_callback);
+                    // chat_client->packet_callback = chat_on_ws_packet_callback;
                 }
             } else {
                 #ifdef SUPPORT_CHINA_MOBILE_AI_REGULATION
                     chat_client = init_websocket_client(url_buf, NULL, 0);
                     if (chat_client != NULL) {
                         chat_client->msg_queue = &chat_msg_queue;   
-                        chat_client->packet_callback = chat_on_ws_packet_callback;
+                        ws_set_packet_callback(chat_client, chat_on_ws_packet_callback);
+                        // chat_client->packet_callback = chat_on_ws_packet_callback;
                     }
                 #else
                     const char* base_url = "ws://118.145.158.207:22080/chat/ws";
@@ -986,7 +987,8 @@ void bk_websocket_demo(void *data) {
                     chat_client = init_websocket_client(full_url, NULL, 0);
                     if (chat_client != NULL) {
                         chat_client->msg_queue = &chat_msg_queue;   
-                        chat_client->packet_callback = chat_on_ws_packet_callback;
+                        ws_set_packet_callback(chat_client, chat_on_ws_packet_callback);
+                        // chat_client->packet_callback = chat_on_ws_packet_callback;
                     }
                 #endif
             }
@@ -1082,7 +1084,10 @@ void bk_websocket_demo(void *data) {
             
             memset_s(recv_buf, 1024, 0, 1024);
             int len = receive_websocket_message_from_queue(&chat_msg_queue, (unsigned char *)recv_buf, 1024, &type, AI_RECEIVE_TIMEOUT_MS);
-            
+            if (len < 1024)
+            {
+                recv_buf[len] = '\0';
+            }
             if (len == -1 || type == WS_CLOSE) {
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WebSocket connection closed");
                 break;
@@ -1102,6 +1107,10 @@ void bk_websocket_demo(void *data) {
                     }
                     AI_UNLOCK();
                     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "recv_buf %s",recv_buf);
+                    if (len < 1024)
+                    {   
+                        recv_buf[len] = '\0';
+                    }
                     chat_result_analysis(recv_buf);
                 }
             }
@@ -1479,26 +1488,30 @@ void bk_websocket_asr(void *data) {
                 asr_client = init_websocket_client("ws://118.145.158.207:22080/asr/ws", NULL, 0);
                 if (asr_client != NULL) {
                     asr_client->msg_queue = &asr_msg_queue;
-                    asr_client->packet_callback = asr_on_ws_packet_callback;
+                    ws_set_packet_callback(asr_client, asr_on_ws_packet_callback);
+                    // asr_client->packet_callback = asr_on_ws_packet_callback;
                 }
             } else if (g_test_server_index == 2) {
                 asr_client = init_websocket_client("ws://110.42.224.129:8910/asr/ws", NULL, 0);
                 if (asr_client != NULL) {
                     asr_client->msg_queue = &asr_msg_queue;
-                    asr_client->packet_callback = asr_on_ws_packet_callback;
+                    ws_set_packet_callback(asr_client, asr_on_ws_packet_callback);
+                    // asr_client->packet_callback = asr_on_ws_packet_callback;
                 }
             } else {
                 if (is_raisound_url) {
                     asr_client = init_websocket_client(url_buf, NULL, 1);
                     if (asr_client != NULL) {
                         asr_client->msg_queue = &asr_msg_queue;
-                        asr_client->packet_callback = asr_on_ws_packet_callback;
+                        ws_set_packet_callback(asr_client, asr_on_ws_packet_callback);
+                        // asr_client->packet_callback = asr_on_ws_packet_callback;
                     }
                 } else {
                     asr_client = init_websocket_client("ws://118.145.158.207:22080/asr/ws", NULL, 0);
                     if (asr_client != NULL) {
                         asr_client->msg_queue = &asr_msg_queue;
-                        asr_client->packet_callback = asr_on_ws_packet_callback;
+                        ws_set_packet_callback(asr_client, asr_on_ws_packet_callback);
+                        // asr_client->packet_callback = asr_on_ws_packet_callback;
                     }
                 }
             }
@@ -1616,7 +1629,10 @@ WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "等待ASR WebSocket握手完成... (%d m
             
             memset_s(asr_recv_buf, 1024, 0, 1024);
             int len = receive_websocket_message_from_queue(&asr_msg_queue, (unsigned char *)asr_recv_buf, 1024, &type, AI_RECEIVE_TIMEOUT_MS);
-            
+            if (len < 1024)
+            {
+                asr_recv_buf[len] = '\0';
+            }
             WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "ASR received: type=%d, len=%d", type, len);
 
             if (type == WS_CLOSE || len == -1) {
@@ -1958,13 +1974,15 @@ void bk_websocket_tts(void *data) {
                 tts_client = init_websocket_client(url_buf, NULL, 1);
                 if (tts_client != NULL) {
                     tts_client->msg_queue = &tts_msg_queue; 
-                    tts_client->packet_callback = tts_on_ws_packet_callback;
+                    ws_set_packet_callback(tts_client, tts_on_ws_packet_callback);
+                    // tts_client->packet_callback = tts_on_ws_packet_callback;
                 }
             } else {
                 tts_client = init_websocket_client("ws://118.145.158.207:22080/tts/stream?audio_buffer_size=512", NULL, 0);
                 if (tts_client != NULL) {
                     tts_client->msg_queue = &tts_msg_queue;
-                    tts_client->packet_callback = tts_on_ws_packet_callback;
+                    ws_set_packet_callback(tts_client, tts_on_ws_packet_callback);
+                    // tts_client->packet_callback = tts_on_ws_packet_callback;
                 }
             }
 
index 4057ee2..999cd6d 100644 (file)
@@ -715,8 +715,8 @@ int ws_process_received_data(WebSocketClient *client, const uint8_t *data, size_
     }
     
     // ========== 新增:打印收到的所有原始数据 ==========
-    printf("\n=== WebSocket Raw Data Received ===\n");
-    printf("Client: %s:%s\n", client->host, client->path);
+    // printf("\n=== WebSocket Raw Data Received ===\n");
+    // printf("Client: %s:%s\n", client->host, client->path);
     printf("Total bytes: %zu\n", len);
     // printf("Raw data (hex): ");
     // // 打印所有数据的十六进制表示
@@ -799,7 +799,7 @@ int ws_process_received_data(WebSocketClient *client, const uint8_t *data, size_
         // 使用新的解析器处理当前数据段
         int result = ws_parse_stream(parser, current_data, remaining_len);
 
-        if(result == -1)
+        if(result <= 0)
         {
             printf("ws_process_received_data: parsing error, reset parser,find next frame. Remaining: %zu bytes\n", remaining_len);
             ws_parser_reset(parser);
@@ -828,16 +828,17 @@ int ws_process_received_data(WebSocketClient *client, const uint8_t *data, size_
             if (header && payload) {
                 printf("WebSocket frame received: opcode=0x%02X, fin=%d, payload_len=%llu\n", 
                        header->opcode, header->fin, header->payload_len);
+                // printf("payload = %s\n",payload);
                 
                 // 打印载荷数据的前几个字节(用于调试)
-                if (payload_len > 0) {
-                    printf("Payload data (first 32 bytes): ");
-                    for (size_t i = 0; i < payload_len && i < 32; i++) {
-                        printf("%02X ", payload[i]);
-                    }
-                    if (payload_len > 32) printf("...");
-                    printf("\n");
-                }
+                // if (payload_len > 0) {
+                //     printf("Payload data (first 32 bytes): ");
+                //     for (size_t i = 0; i < payload_len && i < 32; i++) {
+                //         printf("%02X ", payload[i]);
+                //     }
+                //     if (payload_len > 32) printf("...");
+                //     printf("\n");
+                // }
                 
                 // 根据操作码处理不同类型的消息
                 switch (header->opcode) {
index d695d81..0dda0d5 100644 (file)
@@ -2,7 +2,21 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <string.h>
-#include "wearable_log.h"
+
+// 控制日志输出的宏
+#define ENABLE_DEBUG_LOG 1  // 设置为0可以关闭所有调试输出
+
+#if ENABLE_DEBUG_LOG
+#define WS_LOG(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
+#define WS_LOGI(fmt, ...) printf("[INFO] " fmt "\n", ##__VA_ARGS__)
+#define WS_LOGD(fmt, ...) printf("[DEBUG] " fmt "\n", ##__VA_ARGS__)
+#define WS_LOGE(fmt, ...) printf("[ERROR] " fmt "\n", ##__VA_ARGS__)
+#else
+#define WS_LOG(fmt, ...)
+#define WS_LOGI(fmt, ...)
+#define WS_LOGD(fmt, ...)
+#define WS_LOGE(fmt, ...)
+#endif
 
 #ifdef __cplusplus
 extern "C" {
@@ -10,27 +24,6 @@ extern "C" {
 
 /*
  * WebSocket协议解析器 (RFC 6455)
- * 
- * WebSocket单帧大小限制说明:
- * 
- * 1. 协议层面限制:
- *    - 16位长度字段:最大 65,535 字节 (2^16 - 1)
- *    - 64位长度字段:最大 18,446,744,073,709,551,615 字节 (2^64 - 1)
- * 
- * 2. 控制帧限制(RFC 6455规定):
- *    - Ping/Pong帧:最大125字节负载
- *    - Close帧:最大125字节负载
- * 
- * 3. 应用层限制:
- *    - 默认最大负载长度:65,535字节(16位)
- *    - 可配置最大负载长度:最大1MB
- *    - 可通过 ws_set_max_payload_length() 函数动态配置
- * 
- * 4. 实际限制因素:
- *    - 内存限制
- *    - 网络MTU限制
- *    - 应用层缓冲区大小
- *    - 浏览器/客户端实现限制
  */
 
 // WebSocket帧类型枚举
@@ -91,27 +84,27 @@ static uint64_t g_max_payload_len = WS_MAX_PAYLOAD_LEN_DEFAULT; // 全局最大
 
 // 初始化WebSocket解析器
 ws_parser_t* ws_parser_init() {
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Initializing WebSocket parser");
+    WS_LOGI("WS: Initializing WebSocket parser");
     
     ws_parser_t* parser = (ws_parser_t*)malloc(sizeof(ws_parser_t));
     if (!parser) {
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Failed to allocate memory for parser");
+        WS_LOGE("WS: Failed to allocate memory for parser");
         return NULL;
     }
     
     // 初始化全局缓存
     if (!g_ws_buffer) {
-        WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Allocating global buffer (%d bytes)", WS_BUFFER_SIZE);
+        WS_LOGI("WS: Allocating global buffer (%d bytes)", WS_BUFFER_SIZE);
         g_ws_buffer = (uint8_t*)malloc(WS_BUFFER_SIZE);
         if (!g_ws_buffer) {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Failed to allocate global buffer");
+            WS_LOGE("WS: Failed to allocate global buffer");
             free(parser);
             return NULL;
         }
     }
     
     g_parser_count++;
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Parser count: %d", g_parser_count);
+    WS_LOGI("WS: Parser count: %d", g_parser_count);
     
     // 初始化解析器状态
     parser->state = WS_STATE_START;
@@ -121,7 +114,7 @@ ws_parser_t* ws_parser_init() {
     parser->mask_pos = 0;
     memset(&parser->header, 0, sizeof(ws_header_t));
     
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Parser initialized successfully");
+    WS_LOGI("WS: Parser initialized successfully");
     return parser;
 }
 
@@ -129,8 +122,6 @@ ws_parser_t* ws_parser_init() {
 void ws_parser_reset(ws_parser_t* parser) {
     if (!parser) return;
     
-    // WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Resetting parser state");
-    
     parser->state = WS_STATE_START;
     parser->buffer_pos = 0;
     parser->payload_remaining = 0;
@@ -157,19 +148,19 @@ int validate_control_frame_length(ws_opcode_t opcode, uint64_t payload_len) {
 
 // 配置最大负载长度
 int ws_set_max_payload_length(uint64_t max_len) {
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Setting max payload length to %llu bytes", (unsigned long long)max_len);
+    WS_LOGI("WS: Setting max payload length to %llu bytes", (unsigned long long)max_len);
     
     if (max_len > WS_MAX_PAYLOAD_LEN_MAX) {
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Max payload length %llu exceeds limit %llu", 
+        WS_LOGE("WS: Max payload length %llu exceeds limit %llu", 
             (unsigned long long)max_len, (unsigned long long)WS_MAX_PAYLOAD_LEN_MAX);
         return 0; // 超过最大允许值
     }
     if (max_len < 1) {
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Invalid max payload length: %llu (must be >= 1)", (unsigned long long)max_len);
+        WS_LOGE("WS: Invalid max payload length: %llu (must be >= 1)", (unsigned long long)max_len);
         return 0; // 不能小于1字节
     }
     g_max_payload_len = max_len;
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Max payload length set successfully");
+    WS_LOGI("WS: Max payload length set successfully");
     return 1;
 }
 
@@ -189,7 +180,6 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) {
         case WS_STATE_START:
             parser->state = WS_STATE_READ_HEADER1;
             // 继续执行,处理第一个字节
-            // 注意:这里故意不break,让代码继续执行
         
         case WS_STATE_READ_HEADER1:{
             // 解析第一个头部字节
@@ -199,41 +189,34 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) {
             parser->header.rsv3 = (byte >> 4) & 0x1;
             parser->header.opcode = (ws_opcode_t)(byte & 0x0F);
             
-
-
-            
-            // WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Parse header1 - FIN:%d, RSV:%d%d%d, OPCODE:0x%02X", 
-            //     parser->header.fin, parser->header.rsv1, parser->header.rsv2, parser->header.rsv3, parser->header.opcode);
-            
-
             // 检查 opcode 是否有效
             if (!((parser->header.opcode >= WS_CONTINUATION && parser->header.opcode <= WS_BINARY) ||
                   (parser->header.opcode >= WS_CLOSE && parser->header.opcode <= WS_PONG))) {
-                // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Invalid opcode: 0x%02X", parser->header.opcode);
+                WS_LOGE("WS: Invalid opcode: 0x%02X", parser->header.opcode);
                 parser->state = WS_STATE_ERROR;
                 return -1;
             }
 
-            if(parser->header.fin == 0)
-            {
-                // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Invalid FIN bit: %d", parser->header.fin);
-                // parser->state = WS_STATE_ERROR;
-                // return -1;
-            }
             // 检查RSV位是否都为0(根据RFC6455规范)
-            if (parser->header.rsv1 || parser->header.rsv2 || parser->header.rsv3) {
-                // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Invalid RSV bits: %d%d%d", 
-                //     parser->header.rsv1, parser->header.rsv2, parser->header.rsv3);
-                // parser->state = WS_STATE_ERROR;
-                // return -1;
+            if (!(parser->header.fin == 1 && parser->header.rsv1 == 0 && parser->header.rsv2 == 0 && parser->header.rsv3 == 0)) 
+            {
+                WS_LOGE("WS: Invalid RSV bits: %d%d%d", 
+                    parser->header.rsv1, parser->header.rsv2, parser->header.rsv3);
+                parser->state = WS_STATE_ERROR;
+                return -1;
             }
             
+            WS_LOGD("WS: Parse header1 - FIN:%d, RSV:%d%d%d, OPCODE:0x%02X", 
+                parser->header.fin, parser->header.rsv1, parser->header.rsv2, parser->header.rsv3, parser->header.opcode);
+
+          
+            
             // 保存第一个头部字节到缓存
             if (parser->buffer_pos < WS_BUFFER_SIZE) {
                 parser->buffer[parser->buffer_pos++] = byte;
             } else {
                 parser->state = WS_STATE_ERROR;
-                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Buffer overflow in header1");
+                WS_LOGE("WS: Buffer overflow in header1");
                 return -1;
             }
             
@@ -246,7 +229,7 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) {
             parser->header.mask = (byte >> 7) & 0x1;
             uint8_t payload_len = byte & 0x7F;
             
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "WS: Parse header2 - MASK:%d, LEN:%d", 
+            WS_LOGD("WS: Parse header2 - MASK:%d, LEN:%d", 
                 parser->header.mask, payload_len);
             
             // 保存第二个头部字节到缓存
@@ -254,7 +237,7 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) {
                 parser->buffer[parser->buffer_pos++] = byte;
             } else {
                 parser->state = WS_STATE_ERROR;
-                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Buffer overflow in header2");
+                WS_LOGE("WS: Buffer overflow in header2");
                 return -1;
             }
             
@@ -263,11 +246,11 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) {
                 parser->header.payload_len = payload_len;
                 parser->payload_remaining = payload_len;
                 
-                WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Small payload length: %d bytes", payload_len);
+                WS_LOGI("WS: Small payload length: %d bytes", payload_len);
                 
                 // 验证控制帧长度
                 if (!validate_control_frame_length(parser->header.opcode, payload_len)) {
-                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Control frame length validation failed: opcode=0x%02X, len=%d", 
+                    WS_LOGE("WS: Control frame length validation failed: opcode=0x%02X, len=%d", 
                         parser->header.opcode, payload_len);
                     parser->state = WS_STATE_ERROR;
                     return -1;
@@ -286,13 +269,13 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) {
                 }
             } else if (payload_len == 126) {
                 // 16位长度,需要再读取2个字节
-                WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Extended 16-bit payload length mode");
+                WS_LOGI("WS: Extended 16-bit payload length mode");
                 parser->header.payload_len = 126; // 临时标记
                 parser->payload_remaining = 2;
                 parser->state = WS_STATE_READ_PAYLOAD_LEN;
             } else if (payload_len == 127) {
                 // 64位长度,需要再读取8个字节
-                WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Extended 64-bit payload length mode");
+                WS_LOGI("WS: Extended 64-bit payload length mode");
                 parser->header.payload_len = 127; // 临时标记
                 parser->payload_remaining = 8;
                 parser->state = WS_STATE_READ_PAYLOAD_LEN;
@@ -301,21 +284,21 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) {
         }
             
         case WS_STATE_READ_PAYLOAD_LEN: {
-            // 保存长度字节到缓存
-            if (parser->buffer_pos < WS_BUFFER_SIZE) {
-                parser->buffer[parser->buffer_pos++] = byte;
-            } else {
-                parser->state = WS_STATE_ERROR;
-                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Buffer overflow in payload length");
-                return -1;
-            }
+            // // 保存长度字节到缓存
+            // if (parser->buffer_pos < WS_BUFFER_SIZE) {
+            //     parser->buffer_pos++;
+            // } else {
+            //     parser->state = WS_STATE_ERROR;
+            //     WS_LOGE("WS: Buffer overflow in payload length");
+            //     return -1;
+            // }
             
-            // 累加长度数据 - 修复:使用正确的索引计算
+            // 累加长度数据
             static uint8_t len_bytes[8];
             
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "WS: Reading payload length byte: 0x%02X, remaining: %zu", 
+            WS_LOGD("WS: Reading payload length byte: 0x%02X, remaining: %zu", 
                           byte, parser->payload_remaining);
-            
+
             if (parser->header.payload_len == 126) {
                 // 16位扩展长度:只需要2个字节
                 // 第一个字节存储在len_bytes[0],第二个字节存储在len_bytes[1]
@@ -328,24 +311,26 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) {
                 parser->payload_remaining--;
                 
                 if (parser->payload_remaining == 0) {
-                    // 计算16位长度 - 修复:使用正确的字节顺序
-                    // 注意:网络字节序是大端序,第一个字节是高字节
-                    parser->header.payload_len = (len_bytes[0] << 8) | len_bytes[1];
-                    parser->payload_remaining = parser->header.payload_len;
+                    // 计算16位长度
+                    uint16_t _payload_len = (uint16_t)(len_bytes[0] <<8 ) + len_bytes[1];
+                    printf("len_bytes[0] = %d, len_bytes[1] = %d\n ,payload_len = %d\n", len_bytes[0], len_bytes[1],_payload_len);
+
+                    parser->header.payload_len = _payload_len;
+                    parser->payload_remaining = _payload_len;
                     
-                    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: 16-bit payload length: %d bytes (0x%02X%02X)", 
-                                  parser->header.payload_len, len_bytes[0], len_bytes[1]);
+                    WS_LOGI("WS: 16-bit payload length: %d bytes (0x%02X%02X)", 
+                                  parser->header.payload_len, len_bytes[1], len_bytes[0]);
                     
                     // 验证控制帧长度
                     if (!validate_control_frame_length(parser->header.opcode, parser->header.payload_len)) {
-                        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Control frame length validation failed for 16-bit length");
+                        WS_LOGE("WS: Control frame length validation failed for 16-bit length");
                         parser->state = WS_STATE_ERROR;
                         return -1;
                     }
                     
                     // 检查负载长度是否合理
                     if (parser->header.payload_len > g_max_payload_len) {
-                        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Payload length %d exceeds maximum %llu", 
+                        WS_LOGE("WS: Payload length %d exceeds maximum %llu", 
                             parser->header.payload_len, (unsigned long long)g_max_payload_len);
                         parser->state = WS_STATE_ERROR;
                         return -1;
@@ -353,7 +338,7 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) {
                     
                     // 检查缓存是否足够
                     if (parser->buffer_pos + parser->header.payload_len > WS_BUFFER_SIZE) {
-                        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Buffer overflow: current=%zu, adding=%d, max=%d", 
+                        WS_LOGE("WS: Buffer overflow: current=%zu, adding=%d, max=%d", 
                             parser->buffer_pos, parser->header.payload_len, WS_BUFFER_SIZE);
                         parser->state = WS_STATE_ERROR;
                         return -1;
@@ -361,21 +346,20 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) {
                     
                     // 处理掩码
                     if (parser->header.mask) {
-                        WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Moving to READ_MASK state");
+                        WS_LOGI("WS: Moving to READ_MASK state");
                         parser->state = WS_STATE_READ_MASK;
                     } else {
                         if (parser->payload_remaining == 0) {
-                            WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Zero payload, moving to COMPLETE state");
+                            WS_LOGI("WS: Zero payload, moving to COMPLETE state");
                             parser->state = WS_STATE_COMPLETE;
                             return 1;
                         }
-                        WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Moving to READ_PAYLOAD state");
+                        WS_LOGI("WS: Moving to READ_PAYLOAD state");
                         parser->state = WS_STATE_READ_PAYLOAD;
                     }
                 }
             } else if (parser->header.payload_len == 127) {
                 // 64位扩展长度:需要8个字节
-                // 使用正确的索引:从0开始,按顺序存储
                 size_t byte_index = 8 - parser->payload_remaining;
                 len_bytes[byte_index] = byte;
                 
@@ -389,43 +373,44 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) {
                     }
                     parser->payload_remaining = parser->header.payload_len;
                     
-                    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: 64-bit payload length: %llu bytes", 
+                    WS_LOGI("WS: 64-bit payload length: %llu bytes", 
                         (unsigned long long)parser->header.payload_len);
                     
                     // 验证控制帧长度
                     if (!validate_control_frame_length(parser->header.opcode, parser->header.payload_len)) {
-                        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Control frame length validation failed for 64-bit length");
+                        WS_LOGE("WS: Control frame length validation failed for 64-bit length");
                         parser->state = WS_STATE_ERROR;
                         return -1;
                     }
                     
                     // 检查负载长度是否合理
                     if (parser->header.payload_len > g_max_payload_len) {
-                        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: 64-bit payload length %llu exceeds maximum %llu", 
-                            parser->header.payload_len, (unsigned long long)g_max_payload_len);
+                        WS_LOGE("WS: Payload length %llu exceeds maximum %llu", 
+                            (unsigned long long)parser->header.payload_len, (unsigned long long)g_max_payload_len);
                         parser->state = WS_STATE_ERROR;
                         return -1;
                     }
                     
                     // 检查缓存是否足够
                     if (parser->buffer_pos + parser->header.payload_len > WS_BUFFER_SIZE) {
-                        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Buffer overflow: current=%zu, adding=%llu, max=%d", 
-                            parser->buffer_pos, parser->header.payload_len, WS_BUFFER_SIZE);
+                        WS_LOGE("WS: Buffer overflow: current=%zu, adding=%llu, max=%d", 
+                            parser->buffer_pos, (unsigned long long)parser->header.payload_len, WS_BUFFER_SIZE);
                         parser->state = WS_STATE_ERROR;
                         return -1;
                     }
                     
                     // 处理掩码
                     if (parser->header.mask) {
-                        WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Moving to READ_MASK state");
+                        WS_LOGI("WS: Moving to READ_MASK state");
                         parser->state = WS_STATE_READ_MASK;
+                        return 1;
                     } else {
                         if (parser->payload_remaining == 0) {
-                            WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Zero payload, moving to COMPLETE state");
+                            WS_LOGI("WS: Zero payload, moving to COMPLETE state");
                             parser->state = WS_STATE_COMPLETE;
                             return 1;
                         }
-                        WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Moving to READ_PAYLOAD state");
+                        WS_LOGI("WS: Moving to READ_PAYLOAD state");
                         parser->state = WS_STATE_READ_PAYLOAD;
                     }
                 }
@@ -433,270 +418,540 @@ int ws_parse_byte(ws_parser_t* parser, uint8_t byte) {
             break;
         }
             
-        case WS_STATE_READ_MASK:
+        case WS_STATE_READ_MASK: {
             // 读取掩码密钥
-            parser->header.mask_key[parser->mask_pos++] = byte;
-            
-            // 保存掩码字节到缓存
+            if (parser->mask_pos < 4) {
+                parser->header.mask_key[parser->mask_pos++] = byte;
+                // 保存掩码字节到缓存
             if (parser->buffer_pos < WS_BUFFER_SIZE) {
                 parser->buffer[parser->buffer_pos++] = byte;
             } else {
                 parser->state = WS_STATE_ERROR;
-                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Buffer overflow in mask");
+                WS_LOGI("WS: Buffer overflow in mask");
                 return -1;
             }
             
             // 掩码密钥共4字节
-            if (parser->mask_pos == 4) {
-                WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Mask key read: %02X %02X %02X %02X", 
-                    parser->header.mask_key[0], parser->header.mask_key[1], 
-                    parser->header.mask_key[2], parser->header.mask_key[3]);
-                
-                if (parser->payload_remaining == 0) {
-                    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Frame parsing complete (zero payload)");
-                    parser->state = WS_STATE_COMPLETE;
-                    return 1;
+                if (parser->mask_pos == 4) {
+                    WS_LOGI("WS: Mask key read complete: 0x%02X%02X%02X%02X", 
+                        parser->header.mask_key[0], parser->header.mask_key[1], 
+                        parser->header.mask_key[2], parser->header.mask_key[3]);
+                    
+                    if (parser->payload_remaining == 0) {
+                        parser->state = WS_STATE_COMPLETE;
+                        return 1;
+                    }
+                    parser->state = WS_STATE_READ_PAYLOAD;
                 }
-                parser->state = WS_STATE_READ_PAYLOAD;
             }
             break;
+        }
             
         case WS_STATE_READ_PAYLOAD: {
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "WS: Reading payload byte, remaining: %zu, buffer_pos: %zu", 
-                          parser->payload_remaining, parser->buffer_pos);
-            
-            // 保存负载字节到缓存
+            // 读取负载数据
             if (parser->buffer_pos < WS_BUFFER_SIZE) {
                 parser->buffer[parser->buffer_pos++] = byte;
+                parser->payload_remaining--;
+                
+                if (parser->payload_remaining == 0) {
+                    // 负载读取完成
+                    WS_LOGI("WS: Payload read complete (%zu bytes)", parser->header.payload_len);
+                    
+                    // 如果有掩码,应用掩码解码
+                    if (parser->header.mask) {
+                        // 计算负载在缓存中的起始位置
+                        size_t payload_start = parser->buffer_pos - parser->header.payload_len;
+                        apply_mask(parser->buffer + payload_start, parser->header.payload_len, 
+                                 parser->header.mask_key, 0);
+                        WS_LOGI("WS: Mask applied to payload");
+                    }
+                    
+                    parser->state = WS_STATE_COMPLETE;
+                    return 1;
+                }
             } else {
-                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Buffer overflow in payload reading");
                 parser->state = WS_STATE_ERROR;
+                WS_LOGE("WS: Buffer overflow in payload");
                 return -1;
             }
-            
-            parser->payload_remaining--;
-            
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "WS: After reading byte, remaining: %zu, buffer_pos: %zu", 
-                          parser->payload_remaining, parser->buffer_pos);
-            
-            // 所有负载都已读取
-            if (parser->payload_remaining == 0) {
-                WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Payload read complete (%llu bytes)", 
-                    (unsigned long long)parser->header.payload_len);
-                
-                // 如果有掩码,对负载数据进行解码
-                if (parser->header.mask) {
-                    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Applying mask to payload data");
-                    size_t payload_start = parser->buffer_pos - parser->header.payload_len;
-                    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Payload start: %zu, payload length: %llu", 
-                                  payload_start, parser->header.payload_len);
-                    apply_mask(parser->buffer + payload_start, 
-                              parser->header.payload_len, 
-                              parser->header.mask_key, 
-                              0);
-                }
-                
-                WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Frame parsing complete, transitioning to COMPLETE state");
-                parser->state = WS_STATE_COMPLETE;
-                return 1;
-            }
             break;
         }
             
+        case WS_STATE_COMPLETE:
+            WS_LOGI("WS: Frame parsing complete, transitioning to COMPLETE state");
+            return 1;
+            
+        case WS_STATE_ERROR:
+            WS_LOGE("WS: Parser is in error state");
+            return -1;
+            
         default:
-            break;
+            WS_LOGE("WS: Unknown parser state: %d", parser->state);
+            parser->state = WS_STATE_ERROR;
+            return -1;
     }
     
-    return 0;
+    return 0; // 继续解析
 }
 
-// 处理流数据输入
-// 返回值:解析出的完整包长度,0-未完成,-1-错误
+// 解析数据流
 int ws_parse_stream(ws_parser_t* parser, const uint8_t* data, size_t len) {
     if (!parser || !data || len == 0) {
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Invalid parameters for stream parsing");
+        WS_LOGE("WS: Invalid parameters for ws_parse_stream");
         return -1;
     }
     
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Parsing stream data (%zu bytes), current state: %d, buffer_pos: %zu", 
-                   len, parser->state, parser->buffer_pos);
+    WS_LOGI("WS: Parsing stream data (%zu bytes), current state: %d, buffer_pos: %zu", 
+            len, parser->state, parser->buffer_pos);
     
-    // 重要:如果解析器状态为COMPLETE,说明上一个帧已经完成
-    // 新数据应该开始解析新的帧,需要重置解析器状态
+    // 如果解析器已经完成一个帧,重置状态
     if (parser->state == WS_STATE_COMPLETE) {
-        WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Parser was in COMPLETE state, resetting for new frame");
+        WS_LOGI("WS: Parser was in COMPLETE state, resetting for new frame");
         ws_parser_reset(parser);
     }
-    size_t i=0;
-    for (i = 0; i < len; i++) {
+    
+    int total_processed = 0;
+    
+    for (size_t i = 0; i < len; i++) {
         int result = ws_parse_byte(parser, data[i]);
         
         if (result == 1) {
-            // 解析完成一个包
-            int packet_len = parser->buffer_pos;
-            WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Complete frame parsed (%d bytes total) opcode: %d, payload_len: %llu", 
-                          packet_len, parser->header.opcode, parser->header.payload_len);
-            
-            // 重要:不要在这里重置解析器!
-            // 让上层处理完数据后再调用 ws_parser_reset()
-            // 这样可以确保数据被正确处理后再清理状态
-            return i+1;
+            // 帧解析完成
+            WS_LOGI("WS: Complete frame parsed (%zu bytes total) opcode: %d, payload_len: %llu", 
+                    parser->buffer_pos, parser->header.opcode, (unsigned long long)parser->header.payload_len);
+            total_processed = i + 1;
+            break;
         } else if (result == -1) {
-            // 解析错误,重置解析器
-            // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Parse error at byte %zu, resetting parser, byte: %02X", i, data[i]);
+            // 解析错误
+            WS_LOGE("WS: Parsing error at byte %zu", i);
             ws_parser_reset(parser);
-            continue;
+        // return -1;
+            total_processed = i + 1;
         }
+        // result == 0 继续解析
     }
     
-    // 未完成解析,显示当前状态信息
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Frame parsing incomplete, waiting for more data. State: %d, Buffer: %zu/%zu, Payload remaining: %zu", 
-                   parser->state, parser->buffer_pos, WS_BUFFER_SIZE, parser->payload_remaining);
-    return i+1;
+    if (parser->state == WS_STATE_COMPLETE) {
+        WS_LOGI(" WS_STATE_COMPLETE at %d\n",total_processed);
+    } else if (parser->state == WS_STATE_ERROR) {
+        WS_LOGI(" WS_STATE_ERROR at %d\n",total_processed);
+    } else {
+        // 数据不完整,继续等待更多数据
+        WS_LOGI("WS: Frame parsing incomplete, waiting for more data. State: %d, Buffer: %zu/%d, Payload remaining: %zu", 
+                parser->state, parser->buffer_pos, WS_BUFFER_SIZE, parser->payload_remaining);
+    }
+    return total_processed;
 }
 
-// 新增:打印解析器详细状态信息(用于调试)
-void ws_parser_debug_state(ws_parser_t* parser) {
-    if (!parser) {
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Cannot debug NULL parser");
-        return;
+// 获取解析出的头部信息
+const ws_header_t* ws_get_header(ws_parser_t* parser) {
+    if (!parser || parser->state != WS_STATE_COMPLETE) {
+        return NULL;
+    }
+    return &parser->header;
+}
+
+// 获取完整数据包(包含帧头)
+const uint8_t* ws_get_packet(ws_parser_t* parser) {
+    if (!parser || parser->state != WS_STATE_COMPLETE) {
+        return NULL;
+    }
+    return parser->buffer;
+}
+
+// 获取纯载荷数据
+const uint8_t* ws_get_payload(ws_parser_t* parser) {
+    if (!parser || parser->state != WS_STATE_COMPLETE) {
+        return NULL;
     }
     
-    const char* state_names[] = {
-        "START", "READ_HEADER1", "READ_HEADER2", "READ_PAYLOAD_LEN", 
-        "READ_MASK", "READ_PAYLOAD", "COMPLETE", "ERROR"
-    };
+    // 计算载荷数据的起始位置
+    // 帧头:2字节(基本头部)
+    size_t header_size = 2;
     
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Parser Debug State:");
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "  State: %s (%d)", 
-                   state_names[parser->state], parser->state);
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "  Buffer Position: %zu/%d", 
-                   parser->buffer_pos, WS_BUFFER_SIZE);
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "  Payload Remaining: %zu", 
-                   parser->payload_remaining);
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "  Mask Position: %zu", 
-                   parser->mask_pos);
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "  Header Info:");
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "    FIN: %d", parser->header.fin);
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "    Opcode: 0x%02X", parser->header.opcode);
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "    Mask: %d", parser->header.mask);
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "    Payload Length: %llu", 
-                   (unsigned long long)parser->header.payload_len);
+    // 扩展长度字段
+    if (parser->header.payload_len == 126) {
+        header_size += 2; // 16位长度
+    } else if (parser->header.payload_len == 127) {
+        header_size += 8; // 64位长度
+    }
     
+    // 掩码密钥
     if (parser->header.mask) {
-        WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "    Mask Key: %02X %02X %02X %02X", 
-                       parser->header.mask_key[0], parser->header.mask_key[1], 
-                       parser->header.mask_key[2], parser->header.mask_key[3]);
+        header_size += 4;
     }
     
-    // 打印缓冲区前几个字节(用于调试)
-    if (parser->buffer_pos > 0) {
-        WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "  Buffer (first 16 bytes):");
-        for (size_t i = 0; i < parser->buffer_pos && i < 16; i++) {
-            printf("%02X ", parser->buffer[i]);
-        }
-        if (parser->buffer_pos > 16) printf("...");
-        printf("\n");
+    // 检查载荷数据是否在缓存范围内
+    if (header_size + parser->header.payload_len > parser->buffer_pos) {
+        WS_LOGE("WS: Payload start position %zu exceeds buffer size %zu", header_size, parser->buffer_pos);
+        return NULL;
     }
+    
+    return parser->buffer + header_size;
 }
 
-// 新增:手动重置解析器状态(供上层调用)
-void ws_parser_manual_reset(ws_parser_t* parser) {
-    if (!parser) {
-        WEARABLE_LOGW(WEARABLE_LOG_MODULE_APP, "WS: Attempt to manually reset NULL parser");
-        return;
+// 获取载荷数据长度
+size_t ws_get_payload_length(ws_parser_t* parser) {
+    if (!parser || parser->state != WS_STATE_COMPLETE) {
+        return 0;
     }
-    
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Manual parser reset requested");
-    ws_parser_reset(parser);
+    return parser->header.payload_len;
+}
+
+// 检查解析器是否有错误
+int ws_parser_has_error(ws_parser_t* parser) {
+    return (parser && parser->state == WS_STATE_ERROR) ? 1 : 0;
 }
 
-// 释放解析器资源
+// 获取解析器当前状态
+ws_parse_state_t ws_parser_get_state(ws_parser_t* parser) {
+    return parser ? parser->state : WS_STATE_ERROR;
+}
+
+// 销毁解析器
 void ws_parser_destroy(ws_parser_t* parser) {
     if (parser) {
-        WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Destroying WebSocket parser");
         free(parser);
         g_parser_count--;
         
-        WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Parser count after destroy: %d", g_parser_count);
-        
-        // 只有当没有解析器实例时才释放全局缓存
+        // 如果所有解析器都被销毁,释放全局缓存
         if (g_parser_count == 0 && g_ws_buffer) {
-            WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Releasing global buffer (last parser destroyed)");
             free(g_ws_buffer);
             g_ws_buffer = NULL;
+            WS_LOGI("WS: Global buffer freed");
         }
-    } else {
-        WEARABLE_LOGW(WEARABLE_LOG_MODULE_APP, "WS: Attempt to destroy NULL parser");
+        
+        WS_LOGI("WS: Parser destroyed, remaining parsers: %d", g_parser_count);
     }
 }
 
-// 获取解析出的头部信息
-const ws_header_t* ws_get_header(ws_parser_t* parser) {
-    if (!parser) return NULL;
-    return &parser->header;
-}
-
-// 获取解析出的完整数据包(包含帧头,用于调试)
-const uint8_t* ws_get_packet(ws_parser_t* parser) {
-    if (!parser) return NULL;
-    return parser->buffer;
+#ifdef __cplusplus
 }
-
-// 新增:获取纯载荷数据(不包含帧头)
-const uint8_t* ws_get_payload(ws_parser_t* parser) {
-    if (!parser || parser->state != WS_STATE_COMPLETE) return NULL;
+#endif
+#if 0
+// 多包拆解测试函数
+void test_multiple_frames() {
+    printf("\n=== Multiple WebSocket Frames Test ===\n");
     
-    // 计算载荷数据的起始位置
-    size_t payload_start = 0;
+    // 测试数据:包含多个WebSocket帧
+    uint8_t test_data[] = {
+        // 第一个帧:5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第二个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 BF 99 E6 A0 B7 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0xBF,
+        0x99, 0xE6, 0xA0, 0xB7, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A,
+        0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F,
+        0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第三个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E7 9A 84 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 74, 0x22, 0x3A, 0x22, 0xE7, 0x9A,
+        0x84, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C,
+        0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65,
+        0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第四个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 95 B0 E5 AD 97 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE6, 0x95,
+        0xB0, 0xE5, 0xAD, 0x97, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A,
+        0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F,
+        0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第五个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E7 BB 84 E5 90 88 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE7, 0xBB,
+        0x84, 0xE5, 0x90, 0x88, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A,
+        0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F,
+        0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第六个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 91 A2 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE5, 0x91,
+        0xA2, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C,
+        0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65,
+        0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第七个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E3 80 82 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE3, 0x80,
+        0x82, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C,
+        0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65,
+        0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第八个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BD A0 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE4, 0xBD,
+        0xA0, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C,
+        0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65,
+        0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第九个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 83 BD 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0x83,
+        0xBD, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C,
+        0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65,
+        0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第十个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 AF B4 E8 AF B4 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0xAF,
+        0xB4, 0xE8, 0xAF, 0xB4, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A,
+        0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F,
+        0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第十一个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 BF 99 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0xBF,
+        0x99, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C,
+        0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65,
+        0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第十二个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 87 A0 E4 B8 AA 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE5, 0x87,
+        0xA0, 0xE4, 0xB8, 0xAA, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A,
+        0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F,
+        0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第十三个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 95 B0 E5 AD 97 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE6, 0x95,
+        0xB0, 0xE5, 0xAD, 0x97, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A,
+        0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F,
+        0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第十四个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 98 AF 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE6, 0x98,
+        0xAF, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C,
+        0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65,
+        0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第十五个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 9C A8 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE5, 0x9C,
+        0xA8, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C,
+        0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65,
+        0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D
+    };
     
-    // 基本头部:2字节
-    payload_start += 2;
+    size_t test_data_len = sizeof(test_data);
     
-    // 扩展长度字段
-    uint8_t payload_len_initial = parser->buffer[1] & 0x7F;
-    if (payload_len_initial == 126) {
-        payload_start += 2;  // 16位长度
-    } else if (payload_len_initial == 127) {
-        payload_start += 8;  // 64位长度
+    printf("Test data length: %zu bytes\n", test_data_len);
+    printf("Test data (hex): ");
+    for (size_t i = 0; i < test_data_len; i++) {
+        printf("%02X ", test_data[i]);
+        if ((i + 1) % 16 == 0) printf("\n                    ");
     }
+    printf("\n");
     
-    // 掩码密钥(如果存在)
-    if (parser->header.mask) {
-        payload_start += 4;
+    // 创建解析器
+    ws_parser_t* parser = ws_parser_init();
+    if (!parser) {
+        printf("Failed to create parser\n");
+        return;
     }
     
-    // 确保不越界
-    if (payload_start >= parser->buffer_pos) {
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WS: Payload start position %zu exceeds buffer size %zu", 
-                      payload_start, parser->buffer_pos);
-        return NULL;
-    }
+    // 多包拆解测试
+    printf("\n=== Starting Multi-Frame Parsing ===\n");
     
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "WS: Payload data starts at offset %zu, length %llu", 
-                   payload_start, parser->header.payload_len);
+    size_t offset = 0;
+    int frame_count = 0;
     
-    return parser->buffer + payload_start;
-}
+    while (offset < test_data_len) {
+        printf("\n--- Frame %d ---\n", frame_count + 1);
+        printf("Remaining data: %zu bytes\n", test_data_len - offset);
+        
+        // 解析当前帧
+        int result = ws_parse_stream(parser, test_data + offset, test_data_len - offset);
+        ws_parse_state_t ws_state = ws_parser_get_state(parser);
+        printf("ws_state: %d,result: %d\n", ws_state,result);
+        if (result > 0 && ws_state == WS_STATE_COMPLETE) {
+            frame_count++;
+            printf("Frame %d parsed successfully, consumed %d bytes\n", frame_count, result);
+            
+            const ws_header_t* header = ws_get_header(parser);
+            if (header) {
+                printf("Frame header:\n");
+                printf("  FIN: %d\n", header->fin);
+                printf("  RSV: %d%d%d\n", header->rsv1, header->rsv2, header->rsv3);
+                printf("  Opcode: 0x%02X\n", header->opcode);
+                printf("  Mask: %d\n", header->mask);
+                printf("  Payload length: %llu\n", (unsigned long long)header->payload_len);
+                
+                if (header->mask) {
+                    printf("  Mask key: 0x%02X%02X%02X%02X\n", 
+                        header->mask_key[0], header->mask_key[1], 
+                        header->mask_key[2], header->mask_key[3]);
+                }
+            }
+            
+            const uint8_t* payload = ws_get_payload(parser);
+            size_t payload_len = ws_get_payload_length(parser);
+            
+            if (payload && payload_len > 0) {
+                printf("Payload data:\n");
+                printf("  Length: %zu bytes\n", payload_len);
+                printf("  Hex: ");
+                for (size_t i = 0; i < payload_len && i < 32; i++) {
+                    printf("%02X ", payload[i]);
+                    if ((i + 1) % 16 == 0) printf("\n        ");
+                }
+                if (payload_len > 32) printf("...");
+                printf("\n");
+                
+                printf("  ASCII: ");
+                for (size_t i = 0; i < payload_len && i < 64; i++) {
+                    if (payload[i] >= 32 && payload[i] <= 126) {
+                        printf("%c", payload[i]);
+                    } else {
+                        printf(".");
+                    }
+                }
+                if (payload_len > 64) printf("...");
+                printf("\n");
+            }
+            
+            
+            
+            // 重置解析器状态,准备解析下一个帧
+            ws_parser_reset(parser);
+            
+        } else if (result > 0 && ws_state != WS_STATE_ERROR) {
+            printf("Parser state: %d reset \n", ws_parser_get_state(parser));
+            // 重置解析器状态,准备解析下一个帧
+            ws_parser_reset(parser);
+        } else {
+            printf("Incomplete frame, need more data\n");
+            // printf("Parse error at offset %zu\n", offset);
+            // printf("Parser state: %d\n", ws_parser_get_state(parser));
+        }
 
-// 新增:获取载荷数据长度
-size_t ws_get_payload_length(ws_parser_t* parser) {
-    if (!parser || parser->state != WS_STATE_COMPLETE) return 0;
-    return parser->header.payload_len;
+        // 移动到下一个帧
+        offset += result;
+        // 添加安全检查
+        if (offset >= test_data_len) {
+            printf("Reached end of data\n");
+            break;
+        }
+    }
+    
+    printf("\n=== Multi-Frame Parsing Complete ===\n");
+    printf("Total frames parsed: %d\n", frame_count);
+    printf("Total bytes processed: %zu\n", offset);
+    printf("Remaining bytes: %zu\n", test_data_len - offset);
+    
+    // 清理
+    ws_parser_destroy(parser);
 }
 
-// 新增:检查解析器是否处于错误状态
-int ws_parser_has_error(ws_parser_t* parser) {
-    if (!parser) return 1;
-    return (parser->state == WS_STATE_ERROR);
+// 单帧测试函数(保留原有功能)
+void test_single_frame() {
+    printf("\n=== Single WebSocket Frame Test ===\n");
+    
+    // 测试数据:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 BF 99 E6 A0 B7 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+    uint8_t test_data[] = {
+        0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0xBF,
+        0x99, 0xE6, 0xA0, 0xB7, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A,
+        0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F,
+        0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D
+    };
+    
+    size_t test_data_len = sizeof(test_data);
+    
+    printf("Test data length: %zu bytes\n", test_data_len);
+    printf("Test data (hex): ");
+    for (size_t i = 0; i < test_data_len; i++) {
+        printf("%02X ", test_data[i]);
+        if ((i + 1) % 16 == 0) printf("\n                    ");
+    }
+    printf("\n");
+    
+    // 创建解析器
+    ws_parser_t* parser = ws_parser_init();
+    if (!parser) {
+        printf("Failed to create parser\n");
+        return;
+    }
+    
+    // 解析数据
+    int result = ws_parse_stream(parser, test_data, test_data_len);
+    
+    if (result > 0) {
+        printf("\n=== Parse Result ===\n");
+        printf("Parsed bytes: %d\n", result);
+        
+        const ws_header_t* header = ws_get_header(parser);
+        if (header) {
+            printf("Frame header:\n");
+            printf("  FIN: %d\n", header->fin);
+            printf("  RSV: %d%d%d\n", header->rsv1, header->rsv2, header->rsv3);
+            printf("  Opcode: 0x%02X\n", header->opcode);
+            printf("  Mask: %d\n", header->mask);
+            printf("  Payload length: %llu\n", (unsigned long long)header->payload_len);
+            
+            if (header->mask) {
+                printf("  Mask key: 0x%02X%02X%02X%02X\n", 
+                    header->mask_key[0], header->mask_key[1], 
+                    header->mask_key[2], header->mask_key[3]);
+            }
+        }
+        
+        const uint8_t* payload = ws_get_payload(parser);
+        size_t payload_len = ws_get_payload_length(parser);
+        
+        if (payload && payload_len > 0) {
+            printf("\nPayload data:\n");
+            printf("  Length: %zu bytes\n", payload_len);
+            printf("  Hex: ");
+            for (size_t i = 0; i < payload_len && i < 64; i++) {
+                printf("%02X ", payload[i]);
+                if ((i + 1) % 16 == 0) printf("\n        ");
+            }
+            if (payload_len > 64) printf("...");
+            printf("\n");
+            
+            printf("  ASCII: ");
+            for (size_t i = 0; i < payload_len && i < 64; i++) {
+                if (payload[i] >= 32 && payload[i] <= 126) {
+                    printf("%c", payload[i]);
+                } else {
+                    printf(".");
+                }
+            }
+            if (payload_len > 64) printf("...");
+            printf("\n");
+        }
+        
+        printf("\nParser state: %d\n", ws_parser_get_state(parser));
+        
+    } else if (result == 0) {
+        printf("Incomplete frame, need more data\n");
+        printf("Parser state: %d\n", ws_parser_get_state(parser));
+    } else {
+        printf("Parse error\n");
+        printf("Parser state: %d\n", ws_parser_get_state(parser));
+    }
+    
+    // 清理
+    ws_parser_destroy(parser);
 }
 
-// 新增:获取当前解析状态
-ws_parse_state_t ws_parser_get_state(ws_parser_t* parser) {
-    if (!parser) return WS_STATE_ERROR;
-    return parser->state;
+int main() {
+    printf("WebSocket Parser Standalone Test\n");
+    printf("================================\n");
+    
+    // 测试单帧解析
+    test_single_frame();
+    
+    // 测试多帧解析
+    test_multiple_frames();
+    
+    printf("\nAll tests completed.\n");
+    return 0;
 }
 
-#ifdef __cplusplus
-}
-#endif
+#endif
\ No newline at end of file
index eaf50b5..03cec75 100644 (file)
@@ -1554,7 +1554,7 @@ int tcp_send_and_wait_response(tcp_handle_t handle, const uint8_t* send_data, ui
                 continue;
             } else if (errno == EINPROGRESS) {
                 /* 连接正在进行中,等待连接完成 */
-                printf("tcp_send_and_wait_response: 连接正在进行中,等待连接完成...\n");
+                // printf("tcp_send_and_wait_response: 连接正在进行中,等待连接完成...\n");
                 if ((sys_now() - start_time) > timeout_ms) {
                     printf("tcp_send_and_wait_response: 等待连接完成超时\n");
                     return -1;
diff --git a/test_ws_parser/Makefile b/test_ws_parser/Makefile
new file mode 100644 (file)
index 0000000..99a8e6d
--- /dev/null
@@ -0,0 +1,29 @@
+CC = gcc
+CFLAGS = -Wall -Wextra -std=c99 -O2
+TARGET = websocket_test
+SOURCE = websocket_parser_standalone.cpp
+
+# 默认目标
+all: $(TARGET)
+
+# 编译目标
+$(TARGET): $(SOURCE)
+       $(CC) $(CFLAGS) -o $(TARGET) $(SOURCE)
+
+# 清理
+clean:
+       rm -f $(TARGET)
+
+# 运行测试
+test: $(TARGET)
+       ./$(TARGET)
+
+# 显示帮助
+help:
+       @echo "Available targets:"
+       @echo "  all     - Build the test program"
+       @echo "  clean   - Remove build artifacts"
+       @echo "  test    - Build and run the test"
+       @echo "  help    - Show this help message"
+
+.PHONY: all clean test help
\ No newline at end of file
diff --git a/test_ws_parser/websocket_analysis.py b/test_ws_parser/websocket_analysis.py
new file mode 100644 (file)
index 0000000..203fcde
--- /dev/null
@@ -0,0 +1,211 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+WebSocket数据解析工具
+分析十六进制数据,识别WebSocket帧结构,生成JSON报告
+"""
+
+import json
+import re
+from typing import List, Dict, Any
+
+class WebSocketFrameAnalyzer:
+    def __init__(self):
+        self.frames = []
+        
+    def hex_to_bytes(self, hex_string: str) -> bytes:
+        """将十六进制字符串转换为字节"""
+        # 移除空格和换行符
+        hex_string = re.sub(r'\s+', '', hex_string)
+        return bytes.fromhex(hex_string)
+    
+    def analyze_websocket_frame(self, data: bytes, offset: int) -> Dict[str, Any]:
+        """分析单个WebSocket帧"""
+        if len(data) < 2:
+            return None
+            
+        # 解析第一个字节
+        first_byte = data[0]
+        fin = (first_byte >> 7) & 0x1
+        rsv = (first_byte >> 4) & 0x7
+        opcode = first_byte & 0x0F
+        
+        # 解析第二个字节
+        second_byte = data[1]
+        mask = (second_byte >> 7) & 0x1
+        payload_len = second_byte & 0x7F
+        
+        # 计算帧头大小
+        header_size = 2
+        
+        # 扩展长度字段
+        if payload_len == 126:
+            if len(data) >= 4:
+                extended_len = int.from_bytes(data[2:4], 'big')
+                header_size += 2
+            else:
+                extended_len = 0
+        elif payload_len == 127:
+            if len(data) >= 10:
+                extended_len = int.from_bytes(data[2:10], 'big')
+                header_size += 8
+            else:
+                extended_len = 0
+        else:
+            extended_len = payload_len
+            
+        # 掩码密钥
+        if mask:
+            header_size += 4
+            
+        # 计算总帧大小
+        total_frame_size = header_size + extended_len
+        
+        # 检查数据是否完整
+        if len(data) < total_frame_size:
+            return None
+            
+        # 提取负载数据
+        payload_data = data[header_size:header_size + extended_len]
+        
+        # 如果有掩码,需要解掩码
+        if mask and len(data) >= header_size + 4:
+            mask_key = data[header_size - 4:header_size]
+            unmasked_payload = bytearray(extended_len)
+            for i in range(extended_len):
+                unmasked_payload[i] = payload_data[i] ^ mask_key[i % 4]
+            payload_data = bytes(unmasked_payload)
+        
+        # 解析JSON内容(如果可能)
+        json_content = None
+        try:
+            if payload_data:
+                json_content = json.loads(payload_data.decode('utf-8'))
+        except:
+            pass
+            
+        # 构建帧信息
+        frame_info = {
+            "frame_index": len(self.frames),
+            "offset_in_stream": offset,
+            "frame_header": {
+                "fin": fin,
+                "rsv": rsv,
+                "opcode": opcode,
+                "opcode_name": self.get_opcode_name(opcode),
+                "mask": mask,
+                "payload_length": extended_len
+            },
+            "frame_structure": {
+                "header_size": header_size,
+                "total_frame_size": total_frame_size,
+                "payload_size": extended_len
+            },
+            "raw_data": {
+                "hex": data[:total_frame_size].hex(' ').upper(),
+                "bytes": list(data[:total_frame_size])
+            },
+            "payload": {
+                "hex": payload_data.hex(' ').upper() if payload_data else "",
+                "bytes": list(payload_data) if payload_data else [],
+                "utf8": payload_data.decode('utf-8', errors='ignore') if payload_data else "",
+                "json": json_content
+            }
+        }
+        
+        return frame_info, total_frame_size
+        
+    def get_opcode_name(self, opcode: int) -> str:
+        """获取操作码名称"""
+        opcode_names = {
+            0x0: "CONTINUATION",
+            0x1: "TEXT",
+            0x2: "BINARY",
+            0x8: "CLOSE",
+            0x9: "PING",
+            0xA: "PONG"
+        }
+        return opcode_names.get(opcode, f"UNKNOWN(0x{opcode:02X})")
+        
+    def analyze_stream(self, hex_data: str) -> List[Dict[str, Any]]:
+        """分析整个数据流"""
+        data = self.hex_to_bytes(hex_data)
+        offset = 0
+        
+        print(f"分析数据流,总长度: {len(data)} 字节")
+        
+        while offset < len(data):
+            remaining_data = data[offset:]
+            
+            # 尝试解析一个帧
+            result = self.analyze_websocket_frame(remaining_data, offset)
+            
+            if result is None:
+                # 无法解析,跳过1字节
+                offset += 1
+                continue
+                
+            frame_info, frame_size = result
+            
+            # 添加到帧列表
+            self.frames.append(frame_info)
+            
+            print(f"发现帧 {len(self.frames)}: {frame_info['frame_header']['opcode_name']} "
+                  f"(FIN={frame_info['frame_header']['fin']}, "
+                  f"长度={frame_info['frame_structure']['total_frame_size']} 字节)")
+            
+            # 移动到下一个帧
+            offset += frame_size
+            
+        print(f"总共发现 {len(self.frames)} 个WebSocket帧")
+        return self.frames
+        
+    def save_to_json(self, filename: str):
+        """保存分析结果到JSON文件"""
+        output = {
+            "analysis_summary": {
+                "total_frames": len(self.frames),
+                "total_bytes": sum(frame["frame_structure"]["total_frame_size"] for frame in self.frames)
+            },
+            "frames": self.frames
+        }
+        
+        with open(filename, 'w', encoding='utf-8') as f:
+            json.dump(output, f, ensure_ascii=False, indent=2)
+            
+        print(f"分析结果已保存到: {filename}")
+
+def main():
+    # 原始十六进制数据
+    hex_data = """65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 
+                    74 65 6E 74 22 3A 22 EF BC 8C 22 2C 22 74 61 73 
+                    6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 
+                    69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 
+                    82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BD A0 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 B8 80 E5 AE 9A 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 9C 89 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 BE 88 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 84 89 E5 BF AB 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E7 9A 84 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 BF 83 E6 83 85 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 90 A7 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 46 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 F0 9F 98 98 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 43 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 20 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BD A0 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 8F AF E4 BB A5 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 92 8C 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 88 91 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 AF B4 E8 AF B4 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 9C 89 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BB 80 E4 B9 88 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BA 8B 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 91 80 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 46 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 F0 9F A7 90 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 41 7B 22 74 79 70 65 22 3A 22 65 6E 64 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 6E 75 6C 6C 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 81 7E 00 BB 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 6D 73 67 22 3A 22 73 75 63 63 65 73 73 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 39 34 33 33 37 62 64 65 33 37 22 2C 22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E4 BB 96 E4 BD A0 22 2C 22 69 73 5F 65 6E 64 22 3A 66 61 6C 73 65 2C 22 73 65 6E 74 65 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72 74 5F 74 69 6D 65 22 3A 30 2C 22 65 6E 64 5F 74 69 6D 65 22 3A 30 7D 7D 81 7E 00 C4 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 6D 73 67 22 3A 22 73 75 63 63 65 73 73 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 69 34 33 33 37 62 64 65 33 37 22 2C 22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E7 9C 8B E8 B5 B7 E6 9D A5 E7 8E B0 E5 9C A8 E6 98 AF E6 AD A3 E5 B8 B8 22 2C 22 69 73 5F 65 6E 64 22 3A 66 61 6C 73 65 2C 22 73 65 6E 74 65 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72 74 5F 74 69 6D 65 22 3A 30 2C 22 65 6E 64 5F 74 69 6D 65 22 3A 30 7D 7D 81 7E 00 CD 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 6D 73 67 22 3A 22 73 75 63 63 65 73 73 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 69 34 33 33 37 62 64 65 33 37 22 2C 22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E7 9C 8B E8 B5 B7 E6 9D A5 E7 8E B0 E5 9C A8 E6 98 AF E6 AD A3 E5 B8 B8 22 2C 22 69 73 5F 65 6E 64 22 3A 66 61 6C 73 65 2C 22 73 65 6E 74 65 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72 74 5F 74 69 6D 65 22 3A 30 2C 22 65 6E 64 5F 74 69 6D 65 22 3A 30 7D 7D"""
+    
+    # 创建分析器
+    analyzer = WebSocketFrameAnalyzer()
+    
+    # 分析数据流
+    frames = analyzer.analyze_stream(hex_data)
+    
+    # 保存到JSON文件
+    analyzer.save_to_json("websocket_frames_analysis.json")
+    
+    # 打印简要统计
+    print("\n=== 分析统计 ===")
+    print(f"总帧数: {len(frames)}")
+    print(f"总字节数: {sum(frame['frame_structure']['total_frame_size'] for frame in frames)}")
+    
+    # 按操作码统计
+    opcode_stats = {}
+    for frame in frames:
+        opcode = frame['frame_header']['opcode_name']
+        opcode_stats[opcode] = opcode_stats.get(opcode, 0) + 1
+    
+    print("\n操作码统计:")
+    for opcode, count in opcode_stats.items():
+        print(f"  {opcode}: {count} 帧")
+
+if __name__ == "__main__":
+    main() 
\ No newline at end of file
diff --git a/test_ws_parser/websocket_frames_analysis.json b/test_ws_parser/websocket_frames_analysis.json
new file mode 100644 (file)
index 0000000..52b33eb
--- /dev/null
@@ -0,0 +1,5605 @@
+{
+  "analysis_summary": {
+    "total_frames": 33,
+    "total_bytes": 2361
+  },
+  "frames": [
+    {
+      "frame_index": 0,
+      "offset_in_stream": 0,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 6,
+        "opcode": 5,
+        "opcode_name": "UNKNOWN(0x05)",
+        "mask": 0,
+        "payload_length": 34
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 36,
+        "payload_size": 34
+      },
+      "raw_data": {
+        "hex": "65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 EF BC 8C 22 2C 22 74 61 73 6B 5F 69 64",
+        "bytes": [
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          239,
+          188,
+          140,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100
+        ]
+      },
+      "payload": {
+        "hex": "3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 EF BC 8C 22 2C 22 74 61 73 6B 5F 69 64",
+        "bytes": [
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          239,
+          188,
+          140,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100
+        ],
+        "utf8": ":\"middle\",\"content\":\",\",\"task_id",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 1,
+      "offset_in_stream": 36,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 2,
+        "opcode": 2,
+        "opcode_name": "BINARY",
+        "mask": 0,
+        "payload_length": 58
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 60,
+        "payload_size": 58
+      },
+      "raw_data": {
+        "hex": "22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BD",
+        "bytes": [
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          228,
+          189
+        ]
+      },
+      "payload": {
+        "hex": "22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BD",
+        "bytes": [
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          228,
+          189
+        ],
+        "utf8": "\"\",\"reasoning_content\":\"\"}E{\"type\":\"middle\",\"content\":\"",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 2,
+      "offset_in_stream": 96,
+      "frame_header": {
+        "fin": 1,
+        "rsv": 2,
+        "opcode": 0,
+        "opcode_name": "CONTINUATION",
+        "mask": 0,
+        "payload_length": 34
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 36,
+        "payload_size": 34
+      },
+      "raw_data": {
+        "hex": "A0 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A",
+        "bytes": [
+          160,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58
+        ]
+      },
+      "payload": {
+        "hex": "2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A",
+        "bytes": [
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58
+        ],
+        "utf8": ",\"task_id\":\"\",\"reasoning_content\":",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 3,
+      "offset_in_stream": 132,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 2,
+        "opcode": 2,
+        "opcode_name": "BINARY",
+        "mask": 0,
+        "payload_length": 34
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 36,
+        "payload_size": 34
+      },
+      "raw_data": {
+        "hex": "22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 B8 80",
+        "bytes": [
+          34,
+          34,
+          125,
+          130,
+          72,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          228,
+          184,
+          128
+        ]
+      },
+      "payload": {
+        "hex": "7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 B8 80",
+        "bytes": [
+          125,
+          130,
+          72,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          228,
+          184,
+          128
+        ],
+        "utf8": "}H{\"type\":\"middle\",\"content\":\"一",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 4,
+      "offset_in_stream": 168,
+      "frame_header": {
+        "fin": 1,
+        "rsv": 6,
+        "opcode": 5,
+        "opcode_name": "UNKNOWN(0x05)",
+        "mask": 1,
+        "payload_length": 46
+      },
+      "frame_structure": {
+        "header_size": 6,
+        "total_frame_size": 52,
+        "payload_size": 46
+      },
+      "raw_data": {
+        "hex": "E5 AE 9A 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22",
+        "bytes": [
+          229,
+          174,
+          154,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34
+        ]
+      },
+      "payload": {
+        "hex": "EE 43 5F 49 C5 4B 48 00 A0 00 0E 0E B8 50 49 43 E9 4D 42 4B F4 45 73 41 F5 4C 58 47 F4 56 0E 18 B8 00 51 A0 DF 59 0E 56 E3 52 49 00 A0 00",
+        "bytes": [
+          238,
+          67,
+          95,
+          73,
+          197,
+          75,
+          72,
+          0,
+          160,
+          0,
+          14,
+          14,
+          184,
+          80,
+          73,
+          67,
+          233,
+          77,
+          66,
+          75,
+          244,
+          69,
+          115,
+          65,
+          245,
+          76,
+          88,
+          71,
+          244,
+          86,
+          14,
+          24,
+          184,
+          0,
+          81,
+          160,
+          223,
+          89,
+          14,
+          86,
+          227,
+          82,
+          73,
+          0,
+          160,
+          0
+        ],
+        "utf8": "C_IKH\u0000\u0000\u000e\u000ePICMBKEsALXGV\u000e\u0018\u0000QY\u000eVRI\u0000\u0000",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 5,
+      "offset_in_stream": 220,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 6,
+        "opcode": 13,
+        "opcode_name": "UNKNOWN(0x0D)",
+        "mask": 0,
+        "payload_length": 105
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 107,
+        "payload_size": 105
+      },
+      "raw_data": {
+        "hex": "6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 9C 89 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 BE 88 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22",
+        "bytes": [
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          230,
+          156,
+          137,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          72,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          229,
+          190,
+          136,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34
+        ]
+      },
+      "payload": {
+        "hex": "64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 9C 89 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 BE 88 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22",
+        "bytes": [
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          230,
+          156,
+          137,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          72,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          229,
+          190,
+          136,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34
+        ],
+        "utf8": "ddle\",\"content\":\"有\",\"task_id\":\"\",\"reasoning_content\":\"\"}H{\"type\":\"middle\",\"content\":\"很\",\"task_id\":\"\"",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 6,
+      "offset_in_stream": 327,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 2,
+        "opcode": 12,
+        "opcode_name": "UNKNOWN(0x0C)",
+        "mask": 0,
+        "payload_length": 34
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 36,
+        "payload_size": 34
+      },
+      "raw_data": {
+        "hex": "2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D",
+        "bytes": [
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          72,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109
+        ]
+      },
+      "payload": {
+        "hex": "72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D",
+        "bytes": [
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          72,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109
+        ],
+        "utf8": "reasoning_content\":\"\"}H{\"type\":\"m",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 7,
+      "offset_in_stream": 363,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 6,
+        "opcode": 9,
+        "opcode_name": "PING",
+        "mask": 0,
+        "payload_length": 100
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 102,
+        "payload_size": 100
+      },
+      "raw_data": {
+        "hex": "69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 84 89 E5 BF AB 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E7 9A 84 22 2C 22 74 61 73 6B",
+        "bytes": [
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          230,
+          132,
+          137,
+          229,
+          191,
+          171,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          231,
+          154,
+          132,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107
+        ]
+      },
+      "payload": {
+        "hex": "64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 84 89 E5 BF AB 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E7 9A 84 22 2C 22 74 61 73 6B",
+        "bytes": [
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          230,
+          132,
+          137,
+          229,
+          191,
+          171,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          231,
+          154,
+          132,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107
+        ],
+        "utf8": "dle\",\"content\":\"愉快\",\"task_id\":\"\",\"reasoning_content\":\"\"}E{\"type\":\"middle\",\"content\":\"的\",\"task",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 8,
+      "offset_in_stream": 465,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 5,
+        "opcode": 15,
+        "opcode_name": "UNKNOWN(0x0F)",
+        "mask": 0,
+        "payload_length": 105
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 107,
+        "payload_size": 105
+      },
+      "raw_data": {
+        "hex": "5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 BF 83 E6 83 85 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45",
+        "bytes": [
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          229,
+          191,
+          131,
+          230,
+          131,
+          133,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69
+        ]
+      },
+      "payload": {
+        "hex": "64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 BF 83 E6 83 85 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45",
+        "bytes": [
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          229,
+          191,
+          131,
+          230,
+          131,
+          133,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69
+        ],
+        "utf8": "d\":\"\",\"reasoning_content\":\"\"}E{\"type\":\"middle\",\"content\":\"心情\",\"task_id\":\"\",\"reasoning_content\":\"\"}E",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 9,
+      "offset_in_stream": 572,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 7,
+        "opcode": 11,
+        "opcode_name": "UNKNOWN(0x0B)",
+        "mask": 0,
+        "payload_length": 34
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 36,
+        "payload_size": 34
+      },
+      "raw_data": {
+        "hex": "7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 90 A7 22 2C 22 74 61",
+        "bytes": [
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          229,
+          144,
+          167,
+          34,
+          44,
+          34,
+          116,
+          97
+        ]
+      },
+      "payload": {
+        "hex": "74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 90 A7 22 2C 22 74 61",
+        "bytes": [
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          229,
+          144,
+          167,
+          34,
+          44,
+          34,
+          116,
+          97
+        ],
+        "utf8": "type\":\"middle\",\"content\":\"吧\",\"ta",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 10,
+      "offset_in_stream": 608,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 7,
+        "opcode": 3,
+        "opcode_name": "UNKNOWN(0x03)",
+        "mask": 0,
+        "payload_length": 107
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 109,
+        "payload_size": 107
+      },
+      "raw_data": {
+        "hex": "73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 46 7B 22 74 79 70 65",
+        "bytes": [
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          66,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          70,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101
+        ]
+      },
+      "payload": {
+        "hex": "5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 46 7B 22 74 79 70 65",
+        "bytes": [
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          66,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          70,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101
+        ],
+        "utf8": "_id\":\"\",\"reasoning_content\":\"\"}B{\"type\":\"middle\",\"content\":\"\",\"task_id\":\"\",\"reasoning_content\":\"\"}F{\"type",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 11,
+      "offset_in_stream": 717,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 2,
+        "opcode": 2,
+        "opcode_name": "BINARY",
+        "mask": 0,
+        "payload_length": 58
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 60,
+        "payload_size": 58
+      },
+      "raw_data": {
+        "hex": "22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 F0 9F 98 98 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22",
+        "bytes": [
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          240,
+          159,
+          152,
+          152,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34
+        ]
+      },
+      "payload": {
+        "hex": "22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 F0 9F 98 98 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22",
+        "bytes": [
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          240,
+          159,
+          152,
+          152,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34
+        ],
+        "utf8": "\"middle\",\"content\":\"😘\",\"task_id\":\"\",\"reasoning_content\"",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 12,
+      "offset_in_stream": 777,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 3,
+        "opcode": 10,
+        "opcode_name": "PONG",
+        "mask": 0,
+        "payload_length": 34
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 36,
+        "payload_size": 34
+      },
+      "raw_data": {
+        "hex": "3A 22 22 7D 82 43 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 20 22",
+        "bytes": [
+          58,
+          34,
+          34,
+          125,
+          130,
+          67,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          32,
+          34
+        ]
+      },
+      "payload": {
+        "hex": "22 7D 82 43 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 20 22",
+        "bytes": [
+          34,
+          125,
+          130,
+          67,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          32,
+          34
+        ],
+        "utf8": "\"}C{\"type\":\"middle\",\"content\":\" \"",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 13,
+      "offset_in_stream": 813,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 2,
+        "opcode": 12,
+        "opcode_name": "UNKNOWN(0x0C)",
+        "mask": 0,
+        "payload_length": 34
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 36,
+        "payload_size": 34
+      },
+      "raw_data": {
+        "hex": "2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22",
+        "bytes": [
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34
+        ]
+      },
+      "payload": {
+        "hex": "74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22",
+        "bytes": [
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34
+        ],
+        "utf8": "task_id\":\"\",\"reasoning_content\":\"\"",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 14,
+      "offset_in_stream": 849,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 7,
+        "opcode": 13,
+        "opcode_name": "UNKNOWN(0x0D)",
+        "mask": 1,
+        "payload_length": 2
+      },
+      "frame_structure": {
+        "header_size": 6,
+        "total_frame_size": 8,
+        "payload_size": 2
+      },
+      "raw_data": {
+        "hex": "7D 82 45 7B 22 74 79 70",
+        "bytes": [
+          125,
+          130,
+          69,
+          123,
+          34,
+          116,
+          121,
+          112
+        ]
+      },
+      "payload": {
+        "hex": "3C 0B",
+        "bytes": [
+          60,
+          11
+        ],
+        "utf8": "<\u000b",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 15,
+      "offset_in_stream": 857,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 6,
+        "opcode": 5,
+        "opcode_name": "UNKNOWN(0x05)",
+        "mask": 0,
+        "payload_length": 34
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 36,
+        "payload_size": 34
+      },
+      "raw_data": {
+        "hex": "65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BD A0 22 2C 22 74 61 73 6B 5F 69 64",
+        "bytes": [
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          228,
+          189,
+          160,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100
+        ]
+      },
+      "payload": {
+        "hex": "3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BD A0 22 2C 22 74 61 73 6B 5F 69 64",
+        "bytes": [
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          228,
+          189,
+          160,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100
+        ],
+        "utf8": ":\"middle\",\"content\":\"你\",\"task_id",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 16,
+      "offset_in_stream": 893,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 2,
+        "opcode": 2,
+        "opcode_name": "BINARY",
+        "mask": 0,
+        "payload_length": 58
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 60,
+        "payload_size": 58
+      },
+      "raw_data": {
+        "hex": "22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 8F",
+        "bytes": [
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          72,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          229,
+          143
+        ]
+      },
+      "payload": {
+        "hex": "22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 8F",
+        "bytes": [
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          72,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          229,
+          143
+        ],
+        "utf8": "\"\",\"reasoning_content\":\"\"}H{\"type\":\"middle\",\"content\":\"",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 17,
+      "offset_in_stream": 953,
+      "frame_header": {
+        "fin": 1,
+        "rsv": 2,
+        "opcode": 15,
+        "opcode_name": "UNKNOWN(0x0F)",
+        "mask": 1,
+        "payload_length": 100
+      },
+      "frame_structure": {
+        "header_size": 6,
+        "total_frame_size": 106,
+        "payload_size": 100
+      },
+      "raw_data": {
+        "hex": "AF E4 BB A5 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 92 8C 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65",
+        "bytes": [
+          175,
+          228,
+          187,
+          165,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          229,
+          146,
+          140,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101
+        ]
+      },
+      "payload": {
+        "hex": "99 D1 43 5F D0 FA 4B 48 99 9F 00 0E 97 87 50 49 DA D6 4D 42 D2 CB 45 73 D8 CA 4C 58 DE CB 56 0E 81 87 00 51 39 E0 59 0E CF DC 52 49 99 9F 00 41 D2 C1 46 40 DE 87 0E 0E D8 CA 4C 58 DE CB 56 0E 81 87 C7 BE 37 87 0E 0E CF C4 51 47 E4 CC 46 0E 81 87 00 00 99 D7 47 4D C8 CA 4C 45 D5 C2 7D 4F D4 CB 56 49",
+        "bytes": [
+          153,
+          209,
+          67,
+          95,
+          208,
+          250,
+          75,
+          72,
+          153,
+          159,
+          0,
+          14,
+          151,
+          135,
+          80,
+          73,
+          218,
+          214,
+          77,
+          66,
+          210,
+          203,
+          69,
+          115,
+          216,
+          202,
+          76,
+          88,
+          222,
+          203,
+          86,
+          14,
+          129,
+          135,
+          0,
+          81,
+          57,
+          224,
+          89,
+          14,
+          207,
+          220,
+          82,
+          73,
+          153,
+          159,
+          0,
+          65,
+          210,
+          193,
+          70,
+          64,
+          222,
+          135,
+          14,
+          14,
+          216,
+          202,
+          76,
+          88,
+          222,
+          203,
+          86,
+          14,
+          129,
+          135,
+          199,
+          190,
+          55,
+          135,
+          14,
+          14,
+          207,
+          196,
+          81,
+          71,
+          228,
+          204,
+          70,
+          14,
+          129,
+          135,
+          0,
+          0,
+          153,
+          215,
+          71,
+          77,
+          200,
+          202,
+          76,
+          69,
+          213,
+          194,
+          125,
+          79,
+          212,
+          203,
+          86,
+          73
+        ],
+        "utf8": "C_KH\u0000\u000ePIMBEsLXV\u000e\u0000Q9Y\u000eRI\u0000AF@އ\u000e\u000eLXV\u000eǾ7\u000e\u000eQGF\u000e\u0000\u0000GMLE}OVI",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 18,
+      "offset_in_stream": 1059,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 6,
+        "opcode": 14,
+        "opcode_name": "UNKNOWN(0x0E)",
+        "mask": 0,
+        "payload_length": 116
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 118,
+        "payload_size": 116
+      },
+      "raw_data": {
+        "hex": "6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 88 91 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 AF B4 E8 AF B4 22 2C 22 74",
+        "bytes": [
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          230,
+          136,
+          145,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          72,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          232,
+          175,
+          180,
+          232,
+          175,
+          180,
+          34,
+          44,
+          34,
+          116
+        ]
+      },
+      "payload": {
+        "hex": "22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 88 91 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 AF B4 E8 AF B4 22 2C 22 74",
+        "bytes": [
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          230,
+          136,
+          145,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          72,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          232,
+          175,
+          180,
+          232,
+          175,
+          180,
+          34,
+          44,
+          34,
+          116
+        ],
+        "utf8": "\":\"\"}E{\"type\":\"middle\",\"content\":\"我\",\"task_id\":\"\",\"reasoning_content\":\"\"}H{\"type\":\"middle\",\"content\":\"说说\",\"t",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 19,
+      "offset_in_stream": 1177,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 6,
+        "opcode": 1,
+        "opcode_name": "TEXT",
+        "mask": 0,
+        "payload_length": 115
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 117,
+        "payload_size": 115
+      },
+      "raw_data": {
+        "hex": "61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 9C 89 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D",
+        "bytes": [
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          230,
+          156,
+          137,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          72,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109
+        ]
+      },
+      "payload": {
+        "hex": "6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 9C 89 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 48 7B 22 74 79 70 65 22 3A 22 6D",
+        "bytes": [
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          230,
+          156,
+          137,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          72,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109
+        ],
+        "utf8": "k_id\":\"\",\"reasoning_content\":\"\"}E{\"type\":\"middle\",\"content\":\"有\",\"task_id\":\"\",\"reasoning_content\":\"\"}H{\"type\":\"m",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 20,
+      "offset_in_stream": 1294,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 6,
+        "opcode": 9,
+        "opcode_name": "PING",
+        "mask": 0,
+        "payload_length": 100
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 102,
+        "payload_size": 100
+      },
+      "raw_data": {
+        "hex": "69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BB 80 E4 B9 88 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BA 8B 22 2C 22 74 61 73 6B",
+        "bytes": [
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          228,
+          187,
+          128,
+          228,
+          185,
+          136,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          228,
+          186,
+          139,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107
+        ]
+      },
+      "payload": {
+        "hex": "64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BB 80 E4 B9 88 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BA 8B 22 2C 22 74 61 73 6B",
+        "bytes": [
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          228,
+          187,
+          128,
+          228,
+          185,
+          136,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          228,
+          186,
+          139,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107
+        ],
+        "utf8": "dle\",\"content\":\"什么\",\"task_id\":\"\",\"reasoning_content\":\"\"}E{\"type\":\"middle\",\"content\":\"事\",\"task",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 21,
+      "offset_in_stream": 1396,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 5,
+        "opcode": 15,
+        "opcode_name": "UNKNOWN(0x0F)",
+        "mask": 0,
+        "payload_length": 105
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 107,
+        "payload_size": 105
+      },
+      "raw_data": {
+        "hex": "5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 91 80 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74",
+        "bytes": [
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          229,
+          145,
+          128,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          66,
+          123,
+          34,
+          116
+        ]
+      },
+      "payload": {
+        "hex": "64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 91 80 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74",
+        "bytes": [
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          69,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          229,
+          145,
+          128,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          66,
+          123,
+          34,
+          116
+        ],
+        "utf8": "d\":\"\",\"reasoning_content\":\"\"}E{\"type\":\"middle\",\"content\":\"呀\",\"task_id\":\"\",\"reasoning_content\":\"\"}B{\"t",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 22,
+      "offset_in_stream": 1503,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 7,
+        "opcode": 9,
+        "opcode_name": "PING",
+        "mask": 0,
+        "payload_length": 112
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 114,
+        "payload_size": 112
+      },
+      "raw_data": {
+        "hex": "79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 46 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 F0 9F A7 90 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72",
+        "bytes": [
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          70,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          240,
+          159,
+          167,
+          144,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114
+        ]
+      },
+      "payload": {
+        "hex": "65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 46 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 F0 9F A7 90 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72",
+        "bytes": [
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          70,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          240,
+          159,
+          167,
+          144,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114
+        ],
+        "utf8": "e\":\"middle\",\"content\":\"\",\"task_id\":\"\",\"reasoning_content\":\"\"}F{\"type\":\"middle\",\"content\":\"🧐\",\"task_id\":\"\",\"r",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 23,
+      "offset_in_stream": 1617,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 6,
+        "opcode": 5,
+        "opcode_name": "UNKNOWN(0x05)",
+        "mask": 0,
+        "payload_length": 97
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 99,
+        "payload_size": 97
+      },
+      "raw_data": {
+        "hex": "65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 41 7B 22 74 79 70 65 22 3A",
+        "bytes": [
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          66,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          65,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58
+        ]
+      },
+      "payload": {
+        "hex": "73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 42 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 82 41 7B 22 74 79 70 65 22 3A",
+        "bytes": [
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          66,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58,
+          34,
+          109,
+          105,
+          100,
+          100,
+          108,
+          101,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          130,
+          65,
+          123,
+          34,
+          116,
+          121,
+          112,
+          101,
+          34,
+          58
+        ],
+        "utf8": "soning_content\":\"\"}B{\"type\":\"middle\",\"content\":\"\",\"task_id\":\"\",\"reasoning_content\":\"\"}A{\"type\":",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 24,
+      "offset_in_stream": 1716,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 2,
+        "opcode": 2,
+        "opcode_name": "BINARY",
+        "mask": 0,
+        "payload_length": 101
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 103,
+        "payload_size": 101
+      },
+      "raw_data": {
+        "hex": "22 65 6E 64 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 6E 75 6C 6C 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 81 7E 00 BB 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 6D 73 67 22 3A 22 73 75 63 63 65 73 73 22 2C 22 74 61 73 6B 5F 69",
+        "bytes": [
+          34,
+          101,
+          110,
+          100,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          110,
+          117,
+          108,
+          108,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          129,
+          126,
+          0,
+          187,
+          123,
+          34,
+          115,
+          116,
+          97,
+          116,
+          117,
+          115,
+          34,
+          58,
+          50,
+          48,
+          48,
+          48,
+          48,
+          48,
+          48,
+          48,
+          44,
+          34,
+          109,
+          115,
+          103,
+          34,
+          58,
+          34,
+          115,
+          117,
+          99,
+          99,
+          101,
+          115,
+          115,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105
+        ]
+      },
+      "payload": {
+        "hex": "6E 64 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 6E 75 6C 6C 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D 81 7E 00 BB 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 6D 73 67 22 3A 22 73 75 63 63 65 73 73 22 2C 22 74 61 73 6B 5F 69",
+        "bytes": [
+          110,
+          100,
+          34,
+          44,
+          34,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          110,
+          117,
+          108,
+          108,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          114,
+          101,
+          97,
+          115,
+          111,
+          110,
+          105,
+          110,
+          103,
+          95,
+          99,
+          111,
+          110,
+          116,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          34,
+          125,
+          129,
+          126,
+          0,
+          187,
+          123,
+          34,
+          115,
+          116,
+          97,
+          116,
+          117,
+          115,
+          34,
+          58,
+          50,
+          48,
+          48,
+          48,
+          48,
+          48,
+          48,
+          48,
+          44,
+          34,
+          109,
+          115,
+          103,
+          34,
+          58,
+          34,
+          115,
+          117,
+          99,
+          99,
+          101,
+          115,
+          115,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105
+        ],
+        "utf8": "nd\",\"content\":null,\"task_id\":\"\",\"reasoning_content\":\"\"}~\u0000{\"status\":20000000,\"msg\":\"success\",\"task_i",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 25,
+      "offset_in_stream": 1819,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 6,
+        "opcode": 4,
+        "opcode_name": "UNKNOWN(0x04)",
+        "mask": 0,
+        "payload_length": 34
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 36,
+        "payload_size": 34
+      },
+      "raw_data": {
+        "hex": "64 22 3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 39 34 33 33 37 62 64 65 33 37",
+        "bytes": [
+          100,
+          34,
+          58,
+          34,
+          97,
+          49,
+          97,
+          101,
+          101,
+          50,
+          100,
+          55,
+          53,
+          56,
+          97,
+          54,
+          100,
+          51,
+          57,
+          51,
+          51,
+          97,
+          50,
+          52,
+          54,
+          54,
+          57,
+          52,
+          51,
+          51,
+          55,
+          98,
+          100,
+          101,
+          51,
+          55
+        ]
+      },
+      "payload": {
+        "hex": "3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 39 34 33 33 37 62 64 65 33 37",
+        "bytes": [
+          58,
+          34,
+          97,
+          49,
+          97,
+          101,
+          101,
+          50,
+          100,
+          55,
+          53,
+          56,
+          97,
+          54,
+          100,
+          51,
+          57,
+          51,
+          51,
+          97,
+          50,
+          52,
+          54,
+          54,
+          57,
+          52,
+          51,
+          51,
+          55,
+          98,
+          100,
+          101,
+          51,
+          55
+        ],
+        "utf8": ":\"a1aee2d758a6d3933a246694337bde37",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 26,
+      "offset_in_stream": 1855,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 2,
+        "opcode": 2,
+        "opcode_name": "BINARY",
+        "mask": 0,
+        "payload_length": 44
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 46,
+        "payload_size": 44
+      },
+      "raw_data": {
+        "hex": "22 2C 22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E4 BB 96 E4 BD A0",
+        "bytes": [
+          34,
+          44,
+          34,
+          101,
+          118,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          67,
+          104,
+          97,
+          110,
+          103,
+          101,
+          100,
+          34,
+          44,
+          34,
+          114,
+          101,
+          115,
+          117,
+          108,
+          116,
+          34,
+          58,
+          123,
+          34,
+          114,
+          101,
+          115,
+          117,
+          108,
+          116,
+          34,
+          58,
+          34,
+          228,
+          187,
+          150,
+          228,
+          189,
+          160
+        ]
+      },
+      "payload": {
+        "hex": "22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E4 BB 96 E4 BD A0",
+        "bytes": [
+          34,
+          101,
+          118,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          67,
+          104,
+          97,
+          110,
+          103,
+          101,
+          100,
+          34,
+          44,
+          34,
+          114,
+          101,
+          115,
+          117,
+          108,
+          116,
+          34,
+          58,
+          123,
+          34,
+          114,
+          101,
+          115,
+          117,
+          108,
+          116,
+          34,
+          58,
+          34,
+          228,
+          187,
+          150,
+          228,
+          189,
+          160
+        ],
+        "utf8": "\"event\":\"Changed\",\"result\":{\"result\":\"他你",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 27,
+      "offset_in_stream": 1901,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 2,
+        "opcode": 2,
+        "opcode_name": "BINARY",
+        "mask": 0,
+        "payload_length": 44
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 46,
+        "payload_size": 44
+      },
+      "raw_data": {
+        "hex": "22 2C 22 69 73 5F 65 6E 64 22 3A 66 61 6C 73 65 2C 22 73 65 6E 74 65 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72 74 5F 74 69 6D 65 22",
+        "bytes": [
+          34,
+          44,
+          34,
+          105,
+          115,
+          95,
+          101,
+          110,
+          100,
+          34,
+          58,
+          102,
+          97,
+          108,
+          115,
+          101,
+          44,
+          34,
+          115,
+          101,
+          110,
+          116,
+          101,
+          110,
+          99,
+          101,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          115,
+          116,
+          97,
+          114,
+          116,
+          95,
+          116,
+          105,
+          109,
+          101,
+          34
+        ]
+      },
+      "payload": {
+        "hex": "22 69 73 5F 65 6E 64 22 3A 66 61 6C 73 65 2C 22 73 65 6E 74 65 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72 74 5F 74 69 6D 65 22",
+        "bytes": [
+          34,
+          105,
+          115,
+          95,
+          101,
+          110,
+          100,
+          34,
+          58,
+          102,
+          97,
+          108,
+          115,
+          101,
+          44,
+          34,
+          115,
+          101,
+          110,
+          116,
+          101,
+          110,
+          99,
+          101,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          115,
+          116,
+          97,
+          114,
+          116,
+          95,
+          116,
+          105,
+          109,
+          101,
+          34
+        ],
+        "utf8": "\"is_end\":false,\"sentence_id\":\"\",\"start_time\"",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 28,
+      "offset_in_stream": 1947,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 3,
+        "opcode": 10,
+        "opcode_name": "PONG",
+        "mask": 0,
+        "payload_length": 48
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 50,
+        "payload_size": 48
+      },
+      "raw_data": {
+        "hex": "3A 30 2C 22 65 6E 64 5F 74 69 6D 65 22 3A 30 7D 7D 81 7E 00 C4 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 6D 73 67 22 3A 22 73 75 63",
+        "bytes": [
+          58,
+          48,
+          44,
+          34,
+          101,
+          110,
+          100,
+          95,
+          116,
+          105,
+          109,
+          101,
+          34,
+          58,
+          48,
+          125,
+          125,
+          129,
+          126,
+          0,
+          196,
+          123,
+          34,
+          115,
+          116,
+          97,
+          116,
+          117,
+          115,
+          34,
+          58,
+          50,
+          48,
+          48,
+          48,
+          48,
+          48,
+          48,
+          48,
+          44,
+          34,
+          109,
+          115,
+          103,
+          34,
+          58,
+          34,
+          115,
+          117,
+          99
+        ]
+      },
+      "payload": {
+        "hex": "2C 22 65 6E 64 5F 74 69 6D 65 22 3A 30 7D 7D 81 7E 00 C4 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 6D 73 67 22 3A 22 73 75 63",
+        "bytes": [
+          44,
+          34,
+          101,
+          110,
+          100,
+          95,
+          116,
+          105,
+          109,
+          101,
+          34,
+          58,
+          48,
+          125,
+          125,
+          129,
+          126,
+          0,
+          196,
+          123,
+          34,
+          115,
+          116,
+          97,
+          116,
+          117,
+          115,
+          34,
+          58,
+          50,
+          48,
+          48,
+          48,
+          48,
+          48,
+          48,
+          48,
+          44,
+          34,
+          109,
+          115,
+          103,
+          34,
+          58,
+          34,
+          115,
+          117,
+          99
+        ],
+        "utf8": ",\"end_time\":0}}~\u0000{\"status\":20000000,\"msg\":\"suc",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 29,
+      "offset_in_stream": 1997,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 6,
+        "opcode": 3,
+        "opcode_name": "UNKNOWN(0x03)",
+        "mask": 0,
+        "payload_length": 101
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 103,
+        "payload_size": 101
+      },
+      "raw_data": {
+        "hex": "63 65 73 73 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 69 34 33 33 37 62 64 65 33 37 22 2C 22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E7 9C 8B E8 B5 B7 E6 9D A5 E7 8E B0 E5 9C",
+        "bytes": [
+          99,
+          101,
+          115,
+          115,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          97,
+          49,
+          97,
+          101,
+          101,
+          50,
+          100,
+          55,
+          53,
+          56,
+          97,
+          54,
+          100,
+          51,
+          57,
+          51,
+          51,
+          97,
+          50,
+          52,
+          54,
+          54,
+          105,
+          52,
+          51,
+          51,
+          55,
+          98,
+          100,
+          101,
+          51,
+          55,
+          34,
+          44,
+          34,
+          101,
+          118,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          67,
+          104,
+          97,
+          110,
+          103,
+          101,
+          100,
+          34,
+          44,
+          34,
+          114,
+          101,
+          115,
+          117,
+          108,
+          116,
+          34,
+          58,
+          123,
+          34,
+          114,
+          101,
+          115,
+          117,
+          108,
+          116,
+          34,
+          58,
+          34,
+          231,
+          156,
+          139,
+          232,
+          181,
+          183,
+          230,
+          157,
+          165,
+          231,
+          142,
+          176,
+          229,
+          156
+        ]
+      },
+      "payload": {
+        "hex": "73 73 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 69 34 33 33 37 62 64 65 33 37 22 2C 22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E7 9C 8B E8 B5 B7 E6 9D A5 E7 8E B0 E5 9C",
+        "bytes": [
+          115,
+          115,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          97,
+          49,
+          97,
+          101,
+          101,
+          50,
+          100,
+          55,
+          53,
+          56,
+          97,
+          54,
+          100,
+          51,
+          57,
+          51,
+          51,
+          97,
+          50,
+          52,
+          54,
+          54,
+          105,
+          52,
+          51,
+          51,
+          55,
+          98,
+          100,
+          101,
+          51,
+          55,
+          34,
+          44,
+          34,
+          101,
+          118,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          67,
+          104,
+          97,
+          110,
+          103,
+          101,
+          100,
+          34,
+          44,
+          34,
+          114,
+          101,
+          115,
+          117,
+          108,
+          116,
+          34,
+          58,
+          123,
+          34,
+          114,
+          101,
+          115,
+          117,
+          108,
+          116,
+          34,
+          58,
+          34,
+          231,
+          156,
+          139,
+          232,
+          181,
+          183,
+          230,
+          157,
+          165,
+          231,
+          142,
+          176,
+          229,
+          156
+        ],
+        "utf8": "ss\",\"task_id\":\"a1aee2d758a6d3933a2466i4337bde37\",\"event\":\"Changed\",\"result\":{\"result\":\"看起来现",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 30,
+      "offset_in_stream": 2100,
+      "frame_header": {
+        "fin": 1,
+        "rsv": 2,
+        "opcode": 8,
+        "opcode_name": "CLOSE",
+        "mask": 1,
+        "payload_length": 102
+      },
+      "frame_structure": {
+        "header_size": 6,
+        "total_frame_size": 108,
+        "payload_size": 102
+      },
+      "raw_data": {
+        "hex": "A8 E6 98 AF E6 AD A3 E5 B8 B8 22 2C 22 69 73 5F 65 6E 64 22 3A 66 61 6C 73 65 2C 22 73 65 6E 74 65 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72 74 5F 74 69 6D 65 22 3A 30 2C 22 65 6E 64 5F 74 69 6D 65 22 3A 30 7D 7D 81 7E 00 CD 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 6D 73 67 22 3A 22 73 75 63 63 65",
+        "bytes": [
+          168,
+          230,
+          152,
+          175,
+          230,
+          173,
+          163,
+          229,
+          184,
+          184,
+          34,
+          44,
+          34,
+          105,
+          115,
+          95,
+          101,
+          110,
+          100,
+          34,
+          58,
+          102,
+          97,
+          108,
+          115,
+          101,
+          44,
+          34,
+          115,
+          101,
+          110,
+          116,
+          101,
+          110,
+          99,
+          101,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          115,
+          116,
+          97,
+          114,
+          116,
+          95,
+          116,
+          105,
+          109,
+          101,
+          34,
+          58,
+          48,
+          44,
+          34,
+          101,
+          110,
+          100,
+          95,
+          116,
+          105,
+          109,
+          101,
+          34,
+          58,
+          48,
+          125,
+          125,
+          129,
+          126,
+          0,
+          205,
+          123,
+          34,
+          115,
+          116,
+          97,
+          116,
+          117,
+          115,
+          34,
+          58,
+          50,
+          48,
+          48,
+          48,
+          48,
+          48,
+          48,
+          48,
+          44,
+          34,
+          109,
+          115,
+          103,
+          34,
+          58,
+          34,
+          115,
+          117,
+          99,
+          99,
+          101
+        ]
+      },
+      "payload": {
+        "hex": "3B 4A 5E 15 BA 83 C4 C4 EB F0 83 C3 FC 8D DC CB F9 C3 95 C8 B4 8D 95 C8 F6 DB 83 C3 FB CA B9 C4 FC 8D DC 8F BA 83 C4 DE EC CE 94 D9 C7 DB 8F C0 FD 8D DC 9D B4 8D 83 C3 FC F0 92 C4 F5 CA C4 97 A8 D2 9B 2C E6 AF 2B D6 BA DC 92 CC EC DA 95 8F A2 9D D6 9D A8 9F D6 9D A8 83 C4 C0 EB C8 C4 97 BA DC 93 CE FB CA",
+        "bytes": [
+          59,
+          74,
+          94,
+          21,
+          186,
+          131,
+          196,
+          196,
+          235,
+          240,
+          131,
+          195,
+          252,
+          141,
+          220,
+          203,
+          249,
+          195,
+          149,
+          200,
+          180,
+          141,
+          149,
+          200,
+          246,
+          219,
+          131,
+          195,
+          251,
+          202,
+          185,
+          196,
+          252,
+          141,
+          220,
+          143,
+          186,
+          131,
+          196,
+          222,
+          236,
+          206,
+          148,
+          217,
+          199,
+          219,
+          143,
+          192,
+          253,
+          141,
+          220,
+          157,
+          180,
+          141,
+          131,
+          195,
+          252,
+          240,
+          146,
+          196,
+          245,
+          202,
+          196,
+          151,
+          168,
+          210,
+          155,
+          44,
+          230,
+          175,
+          43,
+          214,
+          186,
+          220,
+          146,
+          204,
+          236,
+          218,
+          149,
+          143,
+          162,
+          157,
+          214,
+          157,
+          168,
+          159,
+          214,
+          157,
+          168,
+          131,
+          196,
+          192,
+          235,
+          200,
+          196,
+          151,
+          186,
+          220,
+          147,
+          206,
+          251,
+          202
+        ],
+        "utf8": ";J^\u0015Õȴۃʹ܏Δۏܝėқ,+ֺܒڕ֝֝ėܓ",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 31,
+      "offset_in_stream": 2208,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 7,
+        "opcode": 3,
+        "opcode_name": "UNKNOWN(0x03)",
+        "mask": 0,
+        "payload_length": 115
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 117,
+        "payload_size": 115
+      },
+      "raw_data": {
+        "hex": "73 73 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 69 34 33 33 37 62 64 65 33 37 22 2C 22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E7 9C 8B E8 B5 B7 E6 9D A5 E7 8E B0 E5 9C A8 E6 98 AF E6 AD A3 E5 B8 B8 22 2C 22 69 73 5F",
+        "bytes": [
+          115,
+          115,
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          97,
+          49,
+          97,
+          101,
+          101,
+          50,
+          100,
+          55,
+          53,
+          56,
+          97,
+          54,
+          100,
+          51,
+          57,
+          51,
+          51,
+          97,
+          50,
+          52,
+          54,
+          54,
+          105,
+          52,
+          51,
+          51,
+          55,
+          98,
+          100,
+          101,
+          51,
+          55,
+          34,
+          44,
+          34,
+          101,
+          118,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          67,
+          104,
+          97,
+          110,
+          103,
+          101,
+          100,
+          34,
+          44,
+          34,
+          114,
+          101,
+          115,
+          117,
+          108,
+          116,
+          34,
+          58,
+          123,
+          34,
+          114,
+          101,
+          115,
+          117,
+          108,
+          116,
+          34,
+          58,
+          34,
+          231,
+          156,
+          139,
+          232,
+          181,
+          183,
+          230,
+          157,
+          165,
+          231,
+          142,
+          176,
+          229,
+          156,
+          168,
+          230,
+          152,
+          175,
+          230,
+          173,
+          163,
+          229,
+          184,
+          184,
+          34,
+          44,
+          34,
+          105,
+          115,
+          95
+        ]
+      },
+      "payload": {
+        "hex": "22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 61 31 61 65 65 32 64 37 35 38 61 36 64 33 39 33 33 61 32 34 36 36 69 34 33 33 37 62 64 65 33 37 22 2C 22 65 76 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74 22 3A 22 E7 9C 8B E8 B5 B7 E6 9D A5 E7 8E B0 E5 9C A8 E6 98 AF E6 AD A3 E5 B8 B8 22 2C 22 69 73 5F",
+        "bytes": [
+          34,
+          44,
+          34,
+          116,
+          97,
+          115,
+          107,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          97,
+          49,
+          97,
+          101,
+          101,
+          50,
+          100,
+          55,
+          53,
+          56,
+          97,
+          54,
+          100,
+          51,
+          57,
+          51,
+          51,
+          97,
+          50,
+          52,
+          54,
+          54,
+          105,
+          52,
+          51,
+          51,
+          55,
+          98,
+          100,
+          101,
+          51,
+          55,
+          34,
+          44,
+          34,
+          101,
+          118,
+          101,
+          110,
+          116,
+          34,
+          58,
+          34,
+          67,
+          104,
+          97,
+          110,
+          103,
+          101,
+          100,
+          34,
+          44,
+          34,
+          114,
+          101,
+          115,
+          117,
+          108,
+          116,
+          34,
+          58,
+          123,
+          34,
+          114,
+          101,
+          115,
+          117,
+          108,
+          116,
+          34,
+          58,
+          34,
+          231,
+          156,
+          139,
+          232,
+          181,
+          183,
+          230,
+          157,
+          165,
+          231,
+          142,
+          176,
+          229,
+          156,
+          168,
+          230,
+          152,
+          175,
+          230,
+          173,
+          163,
+          229,
+          184,
+          184,
+          34,
+          44,
+          34,
+          105,
+          115,
+          95
+        ],
+        "utf8": "\",\"task_id\":\"a1aee2d758a6d3933a2466i4337bde37\",\"event\":\"Changed\",\"result\":{\"result\":\"看起来现在是正常\",\"is_",
+        "json": null
+      }
+    },
+    {
+      "frame_index": 32,
+      "offset_in_stream": 2327,
+      "frame_header": {
+        "fin": 0,
+        "rsv": 6,
+        "opcode": 4,
+        "opcode_name": "UNKNOWN(0x04)",
+        "mask": 0,
+        "payload_length": 34
+      },
+      "frame_structure": {
+        "header_size": 2,
+        "total_frame_size": 36,
+        "payload_size": 34
+      },
+      "raw_data": {
+        "hex": "64 22 3A 66 61 6C 73 65 2C 22 73 65 6E 74 65 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72 74 5F 74 69 6D",
+        "bytes": [
+          100,
+          34,
+          58,
+          102,
+          97,
+          108,
+          115,
+          101,
+          44,
+          34,
+          115,
+          101,
+          110,
+          116,
+          101,
+          110,
+          99,
+          101,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          115,
+          116,
+          97,
+          114,
+          116,
+          95,
+          116,
+          105,
+          109
+        ]
+      },
+      "payload": {
+        "hex": "3A 66 61 6C 73 65 2C 22 73 65 6E 74 65 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72 74 5F 74 69 6D",
+        "bytes": [
+          58,
+          102,
+          97,
+          108,
+          115,
+          101,
+          44,
+          34,
+          115,
+          101,
+          110,
+          116,
+          101,
+          110,
+          99,
+          101,
+          95,
+          105,
+          100,
+          34,
+          58,
+          34,
+          34,
+          44,
+          34,
+          115,
+          116,
+          97,
+          114,
+          116,
+          95,
+          116,
+          105,
+          109
+        ],
+        "utf8": ":false,\"sentence_id\":\"\",\"start_tim",
+        "json": null
+      }
+    }
+  ]
+}
\ No newline at end of file
diff --git a/test_ws_parser/websocket_parser_standalone.cpp b/test_ws_parser/websocket_parser_standalone.cpp
new file mode 100644 (file)
index 0000000..c02304b
--- /dev/null
@@ -0,0 +1,989 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+// 控制日志输出的宏
+#define ENABLE_DEBUG_LOG 1  // 设置为0可以关闭所有调试输出
+
+#if ENABLE_DEBUG_LOG
+#define WS_LOG(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
+#define WS_LOGI(fmt, ...) printf("[INFO] " fmt "\n", ##__VA_ARGS__)
+#define WS_LOGD(fmt, ...) printf("[DEBUG] " fmt "\n", ##__VA_ARGS__)
+#define WS_LOGE(fmt, ...) printf("[ERROR] " fmt "\n", ##__VA_ARGS__)
+#else
+#define WS_LOG(fmt, ...)
+#define WS_LOGI(fmt, ...)
+#define WS_LOGD(fmt, ...)
+#define WS_LOGE(fmt, ...)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * WebSocket协议解析器 (RFC 6455)
+ */
+
+// WebSocket帧类型枚举
+typedef enum {
+    WS_CONTINUATION = 0x0,
+    WS_TEXT = 0x1,
+    WS_BINARY = 0x2,
+    WS_CLOSE = 0x8,
+    WS_PING = 0x9,
+    WS_PONG = 0xA
+} ws_opcode_t;
+
+// WebSocket解析状态
+typedef enum {
+    WS_STATE_START,
+    WS_STATE_READ_HEADER1,
+    WS_STATE_READ_HEADER2,
+    WS_STATE_READ_PAYLOAD_LEN,
+    WS_STATE_READ_MASK,
+    WS_STATE_READ_PAYLOAD,
+    WS_STATE_COMPLETE,
+    WS_STATE_ERROR
+} ws_parse_state_t;
+
+// WebSocket帧头部信息
+typedef struct {
+    uint8_t fin;           // 帧结束标志
+    uint8_t rsv1;          // 保留位1
+    uint8_t rsv2;          // 保留位2
+    uint8_t rsv3;          // 保留位3
+    ws_opcode_t opcode;    // 操作码
+    uint8_t mask;          // 掩码标志
+    uint64_t payload_len;  // 负载长度
+    uint8_t mask_key[4];   // 掩码密钥
+} ws_header_t;
+
+// WebSocket解析上下文
+typedef struct {
+    ws_parse_state_t state;       // 当前解析状态
+    ws_header_t header;           // 解析出的头部信息
+    uint8_t* buffer;              // 数据缓存
+    size_t buffer_pos;            // 缓存当前位置
+    size_t payload_remaining;     // 剩余需要读取的负载长度
+    size_t mask_pos;              // 掩码读取位置
+} ws_parser_t;
+
+// 全局动态分配缓存(1024字节)
+uint8_t* g_ws_buffer = NULL;
+#define WS_BUFFER_SIZE 1024
+
+// WebSocket协议长度限制配置
+#define WS_MAX_PAYLOAD_LEN_DEFAULT 65535    // 默认最大负载长度(16位)
+#define WS_MAX_PAYLOAD_LEN_MAX     1048576  // 最大允许的负载长度(1MB)
+#define WS_CONTROL_FRAME_MAX_LEN   125      // 控制帧最大负载长度(RFC 6455规定)
+
+static int g_parser_count = 0;    // 解析器实例计数
+static uint64_t g_max_payload_len = WS_MAX_PAYLOAD_LEN_DEFAULT; // 全局最大负载长度配置
+
+// 初始化WebSocket解析器
+ws_parser_t* ws_parser_init() {
+    WS_LOGI("WS: Initializing WebSocket parser");
+    
+    ws_parser_t* parser = (ws_parser_t*)malloc(sizeof(ws_parser_t));
+    if (!parser) {
+        WS_LOGE("WS: Failed to allocate memory for parser");
+        return NULL;
+    }
+    
+    // 初始化全局缓存
+    if (!g_ws_buffer) {
+        WS_LOGI("WS: Allocating global buffer (%d bytes)", WS_BUFFER_SIZE);
+        g_ws_buffer = (uint8_t*)malloc(WS_BUFFER_SIZE);
+        if (!g_ws_buffer) {
+            WS_LOGE("WS: Failed to allocate global buffer");
+            free(parser);
+            return NULL;
+        }
+    }
+    
+    g_parser_count++;
+    WS_LOGI("WS: Parser count: %d", g_parser_count);
+    
+    // 初始化解析器状态
+    parser->state = WS_STATE_START;
+    parser->buffer = g_ws_buffer;
+    parser->buffer_pos = 0;
+    parser->payload_remaining = 0;
+    parser->mask_pos = 0;
+    memset(&parser->header, 0, sizeof(ws_header_t));
+    
+    WS_LOGI("WS: Parser initialized successfully");
+    return parser;
+}
+
+// 重置解析器状态
+void ws_parser_reset(ws_parser_t* parser) {
+    if (!parser) return;
+    
+    parser->state = WS_STATE_START;
+    parser->buffer_pos = 0;
+    parser->payload_remaining = 0;
+    parser->mask_pos = 0;
+    memset(&parser->header, 0, sizeof(ws_header_t));
+}
+
+// 应用掩码解码
+void apply_mask(uint8_t* data, size_t len, const uint8_t* mask_key, size_t offset) {
+    for (size_t i = 0; i < len; i++) {
+        data[i] ^= mask_key[(offset + i) % 4];
+    }
+}
+
+// 验证控制帧长度
+int validate_control_frame_length(ws_opcode_t opcode, uint64_t payload_len) {
+    if (opcode >= WS_CLOSE && opcode <= WS_PONG) {
+        if (payload_len > WS_CONTROL_FRAME_MAX_LEN) {
+            return 0; // 控制帧长度不能超过125字节
+        }
+    }
+    return 1;
+}
+
+// 配置最大负载长度
+int ws_set_max_payload_length(uint64_t max_len) {
+    WS_LOGI("WS: Setting max payload length to %llu bytes", (unsigned long long)max_len);
+    
+    if (max_len > WS_MAX_PAYLOAD_LEN_MAX) {
+        WS_LOGE("WS: Max payload length %llu exceeds limit %llu", 
+            (unsigned long long)max_len, (unsigned long long)WS_MAX_PAYLOAD_LEN_MAX);
+        return 0; // 超过最大允许值
+    }
+    if (max_len < 1) {
+        WS_LOGE("WS: Invalid max payload length: %llu (must be >= 1)", (unsigned long long)max_len);
+        return 0; // 不能小于1字节
+    }
+    g_max_payload_len = max_len;
+    WS_LOGI("WS: Max payload length set successfully");
+    return 1;
+}
+
+// 获取当前配置的最大负载长度
+uint64_t ws_get_max_payload_length(void) {
+    return g_max_payload_len;
+}
+
+// 解析单个字节
+// 返回值:0-继续解析,1-解析完成一个帧,-1-错误
+int ws_parse_byte(ws_parser_t* parser, uint8_t byte) {
+    if (!parser || parser->state == WS_STATE_ERROR) {
+        return -1;
+    }
+
+    switch (parser->state) {
+        case WS_STATE_START:
+            parser->state = WS_STATE_READ_HEADER1;
+            // 继续执行,处理第一个字节
+        
+        case WS_STATE_READ_HEADER1:{
+            // 解析第一个头部字节
+            parser->header.fin = (byte >> 7) & 0x1;
+            parser->header.rsv1 = (byte >> 6) & 0x1;
+            parser->header.rsv2 = (byte >> 5) & 0x1;
+            parser->header.rsv3 = (byte >> 4) & 0x1;
+            parser->header.opcode = (ws_opcode_t)(byte & 0x0F);
+            
+            // 检查 opcode 是否有效
+            if (!((parser->header.opcode >= WS_CONTINUATION && parser->header.opcode <= WS_BINARY) ||
+                  (parser->header.opcode >= WS_CLOSE && parser->header.opcode <= WS_PONG))) {
+                WS_LOGE("WS: Invalid opcode: 0x%02X", parser->header.opcode);
+                parser->state = WS_STATE_ERROR;
+                return -1;
+            }
+
+            // 检查RSV位是否都为0(根据RFC6455规范)
+            if (!(parser->header.fin == 1 && parser->header.rsv1 == 0 && parser->header.rsv2 == 0 && parser->header.rsv3 == 0)) 
+            {
+                WS_LOGE("WS: Invalid RSV bits: %d%d%d", 
+                    parser->header.rsv1, parser->header.rsv2, parser->header.rsv3);
+                parser->state = WS_STATE_ERROR;
+                return -1;
+            }
+            
+            WS_LOGD("WS: Parse header1 - FIN:%d, RSV:%d%d%d, OPCODE:0x%02X", 
+                parser->header.fin, parser->header.rsv1, parser->header.rsv2, parser->header.rsv3, parser->header.opcode);
+
+          
+            
+            // 保存第一个头部字节到缓存
+            if (parser->buffer_pos < WS_BUFFER_SIZE) {
+                parser->buffer[parser->buffer_pos++] = byte;
+            } else {
+                parser->state = WS_STATE_ERROR;
+                WS_LOGE("WS: Buffer overflow in header1");
+                return -1;
+            }
+            
+            parser->state = WS_STATE_READ_HEADER2;
+            break;
+        }
+            
+        case WS_STATE_READ_HEADER2: {
+            // 解析第二个头部字节
+            parser->header.mask = (byte >> 7) & 0x1;
+            uint8_t payload_len = byte & 0x7F;
+            
+            WS_LOGD("WS: Parse header2 - MASK:%d, LEN:%d", 
+                parser->header.mask, payload_len);
+            
+            // 保存第二个头部字节到缓存
+            if (parser->buffer_pos < WS_BUFFER_SIZE) {
+                parser->buffer[parser->buffer_pos++] = byte;
+            } else {
+                parser->state = WS_STATE_ERROR;
+                WS_LOGE("WS: Buffer overflow in header2");
+                return -1;
+            }
+            
+            // 处理负载长度
+            if (payload_len <= 125) {
+                parser->header.payload_len = payload_len;
+                parser->payload_remaining = payload_len;
+                
+                WS_LOGI("WS: Small payload length: %d bytes", payload_len);
+                
+                // 验证控制帧长度
+                if (!validate_control_frame_length(parser->header.opcode, payload_len)) {
+                    WS_LOGE("WS: Control frame length validation failed: opcode=0x%02X, len=%d", 
+                        parser->header.opcode, payload_len);
+                    parser->state = WS_STATE_ERROR;
+                    return -1;
+                }
+                
+                // 如果有掩码,下一步读取掩码
+                if (parser->header.mask) {
+                    parser->state = WS_STATE_READ_MASK;
+                } else {
+                    // 无掩码,直接读取负载
+                    if (parser->payload_remaining == 0) {
+                        parser->state = WS_STATE_COMPLETE;
+                        return 1;
+                    }
+                    parser->state = WS_STATE_READ_PAYLOAD;
+                }
+            } else if (payload_len == 126) {
+                // 16位长度,需要再读取2个字节
+                WS_LOGI("WS: Extended 16-bit payload length mode");
+                parser->header.payload_len = 126; // 临时标记
+                parser->payload_remaining = 2;
+                parser->state = WS_STATE_READ_PAYLOAD_LEN;
+            } else if (payload_len == 127) {
+                // 64位长度,需要再读取8个字节
+                WS_LOGI("WS: Extended 64-bit payload length mode");
+                parser->header.payload_len = 127; // 临时标记
+                parser->payload_remaining = 8;
+                parser->state = WS_STATE_READ_PAYLOAD_LEN;
+            }
+            break;
+        }
+            
+        case WS_STATE_READ_PAYLOAD_LEN: {
+            // 保存长度字节到缓存
+            // if (parser->buffer_pos < WS_BUFFER_SIZE) {
+            //     parser->buffer_pos++;
+            // } else {
+            //     parser->state = WS_STATE_ERROR;
+            //     WS_LOGE("WS: Buffer overflow in payload length");
+            //     return -1;
+            // }
+            
+            // 累加长度数据
+            static uint8_t len_bytes[8];
+            
+            WS_LOGD("WS: Reading payload length byte: 0x%02X, remaining: %zu", 
+                          byte, parser->payload_remaining);
+            
+            if (parser->header.payload_len == 126) {
+                // 16位扩展长度:只需要2个字节
+                if (parser->payload_remaining == 2) {
+                    len_bytes[0] = byte;  // 高字节
+                } else if (parser->payload_remaining == 1) {
+                    len_bytes[1] = byte;  // 低字节
+                }
+                
+                parser->payload_remaining--;
+                
+                if (parser->payload_remaining == 0) {
+                    // 计算16位长度
+                    parser->header.payload_len = (len_bytes[0] << 8) | len_bytes[1];
+                    parser->payload_remaining = parser->header.payload_len;
+                    
+                    WS_LOGI("WS: 16-bit payload length: %d bytes (0x%02X%02X)", 
+                                  parser->header.payload_len, len_bytes[0], len_bytes[1]);
+                    
+                    // 验证控制帧长度
+                    if (!validate_control_frame_length(parser->header.opcode, parser->header.payload_len)) {
+                        WS_LOGE("WS: Control frame length validation failed for 16-bit length");
+                        parser->state = WS_STATE_ERROR;
+                        return -1;
+                    }
+                    
+                    // 检查负载长度是否合理
+                    if (parser->header.payload_len > g_max_payload_len) {
+                        WS_LOGE("WS: Payload length %d exceeds maximum %llu", 
+                            parser->header.payload_len, (unsigned long long)g_max_payload_len);
+                        parser->state = WS_STATE_ERROR;
+                        return -1;
+                    }
+                    
+                    // 检查缓存是否足够
+                    if (parser->buffer_pos + parser->header.payload_len > WS_BUFFER_SIZE) {
+                        WS_LOGE("WS: Buffer overflow: current=%zu, adding=%d, max=%d", 
+                            parser->buffer_pos, parser->header.payload_len, WS_BUFFER_SIZE);
+                        parser->state = WS_STATE_ERROR;
+                        return -1;
+                    }
+                    
+                    // 处理掩码
+                    if (parser->header.mask) {
+                        WS_LOGI("WS: Moving to READ_MASK state");
+                        parser->state = WS_STATE_READ_MASK;
+                    } else {
+                        if (parser->payload_remaining == 0) {
+                            WS_LOGI("WS: Zero payload, moving to COMPLETE state");
+                            parser->state = WS_STATE_COMPLETE;
+                            return 1;
+                        }
+                        WS_LOGI("WS: Moving to READ_PAYLOAD state");
+                        parser->state = WS_STATE_READ_PAYLOAD;
+                    }
+                }
+            } else if (parser->header.payload_len == 127) {
+                // 64位扩展长度:需要8个字节
+                size_t byte_index = 8 - parser->payload_remaining;
+                len_bytes[byte_index] = byte;
+                
+                parser->payload_remaining--;
+                
+                if (parser->payload_remaining == 0) {
+                    // 计算64位长度
+                    parser->header.payload_len = 0;
+                    for (int i = 0; i < 8; i++) {
+                        parser->header.payload_len = (parser->header.payload_len << 8) | len_bytes[i];
+                    }
+                    parser->payload_remaining = parser->header.payload_len;
+                    
+                    WS_LOGI("WS: 64-bit payload length: %llu bytes", 
+                        (unsigned long long)parser->header.payload_len);
+                    
+                    // 验证控制帧长度
+                    if (!validate_control_frame_length(parser->header.opcode, parser->header.payload_len)) {
+                        WS_LOGE("WS: Control frame length validation failed for 64-bit length");
+                        parser->state = WS_STATE_ERROR;
+                        return -1;
+                    }
+                    
+                    // 检查负载长度是否合理
+                    if (parser->header.payload_len > g_max_payload_len) {
+                        WS_LOGE("WS: Payload length %llu exceeds maximum %llu", 
+                            (unsigned long long)parser->header.payload_len, (unsigned long long)g_max_payload_len);
+                        parser->state = WS_STATE_ERROR;
+                        return -1;
+                    }
+                    
+                    // 检查缓存是否足够
+                    if (parser->buffer_pos + parser->header.payload_len > WS_BUFFER_SIZE) {
+                        WS_LOGE("WS: Buffer overflow: current=%zu, adding=%llu, max=%d", 
+                            parser->buffer_pos, (unsigned long long)parser->header.payload_len, WS_BUFFER_SIZE);
+                        parser->state = WS_STATE_ERROR;
+                        return -1;
+                    }
+                    
+                    // 处理掩码
+                    if (parser->header.mask) {
+                        WS_LOGI("WS: Moving to READ_MASK state");
+                        parser->state = WS_STATE_READ_MASK;
+                        return 1;
+                    } else {
+                        if (parser->payload_remaining == 0) {
+                            WS_LOGI("WS: Zero payload, moving to COMPLETE state");
+                            parser->state = WS_STATE_COMPLETE;
+                            return 1;
+                        }
+                        WS_LOGI("WS: Moving to READ_PAYLOAD state");
+                        parser->state = WS_STATE_READ_PAYLOAD;
+                    }
+                }
+            }
+            break;
+        }
+            
+        case WS_STATE_READ_MASK: {
+            // 读取掩码密钥
+            if (parser->mask_pos < 4) {
+                parser->header.mask_key[parser->mask_pos++] = byte;
+                
+                if (parser->mask_pos == 4) {
+                    WS_LOGI("WS: Mask key read complete: 0x%02X%02X%02X%02X", 
+                        parser->header.mask_key[0], parser->header.mask_key[1], 
+                        parser->header.mask_key[2], parser->header.mask_key[3]);
+                    
+                    if (parser->payload_remaining == 0) {
+                        parser->state = WS_STATE_COMPLETE;
+                        return 1;
+                    }
+                    parser->state = WS_STATE_READ_PAYLOAD;
+                }
+            }
+            break;
+        }
+            
+        case WS_STATE_READ_PAYLOAD: {
+            // 读取负载数据
+            if (parser->buffer_pos < WS_BUFFER_SIZE) {
+                parser->buffer[parser->buffer_pos++] = byte;
+                parser->payload_remaining--;
+                
+                if (parser->payload_remaining == 0) {
+                    // 负载读取完成
+                    WS_LOGI("WS: Payload read complete (%zu bytes)", parser->header.payload_len);
+                    
+                    // 如果有掩码,应用掩码解码
+                    if (parser->header.mask) {
+                        // 计算负载在缓存中的起始位置
+                        size_t payload_start = parser->buffer_pos - parser->header.payload_len;
+                        apply_mask(parser->buffer + payload_start, parser->header.payload_len, 
+                                 parser->header.mask_key, 0);
+                        WS_LOGI("WS: Mask applied to payload");
+                    }
+                    
+                    parser->state = WS_STATE_COMPLETE;
+                    return 1;
+                }
+            } else {
+                parser->state = WS_STATE_ERROR;
+                WS_LOGE("WS: Buffer overflow in payload");
+                return -1;
+            }
+            break;
+        }
+            
+        case WS_STATE_COMPLETE:
+            WS_LOGI("WS: Frame parsing complete, transitioning to COMPLETE state");
+            return 1;
+            
+        case WS_STATE_ERROR:
+            WS_LOGE("WS: Parser is in error state");
+            return -1;
+            
+        default:
+            WS_LOGE("WS: Unknown parser state: %d", parser->state);
+            parser->state = WS_STATE_ERROR;
+            return -1;
+    }
+    
+    return 0; // 继续解析
+}
+
+// 解析数据流
+int ws_parse_stream(ws_parser_t* parser, const uint8_t* data, size_t len) {
+    if (!parser || !data || len == 0) {
+        WS_LOGE("WS: Invalid parameters for ws_parse_stream");
+        return -1;
+    }
+    
+    WS_LOGI("WS: Parsing stream data (%zu bytes), current state: %d, buffer_pos: %zu", 
+            len, parser->state, parser->buffer_pos);
+    
+    // 如果解析器已经完成一个帧,重置状态
+    if (parser->state == WS_STATE_COMPLETE) {
+        WS_LOGI("WS: Parser was in COMPLETE state, resetting for new frame");
+        ws_parser_reset(parser);
+    }
+    
+    int total_processed = 0;
+    
+    for (size_t i = 0; i < len; i++) {
+        int result = ws_parse_byte(parser, data[i]);
+        
+        if (result == 1) {
+            // 帧解析完成
+            WS_LOGI("WS: Complete frame parsed (%zu bytes total) opcode: %d, payload_len: %llu", 
+                    parser->buffer_pos, parser->header.opcode, (unsigned long long)parser->header.payload_len);
+            total_processed = i + 1;
+            break;
+        } else if (result == -1) {
+            // 解析错误
+            WS_LOGE("WS: Parsing error at byte %zu", i);
+            ws_parser_reset(parser);
+        // return -1;
+            total_processed = i + 1;
+        }
+        // result == 0 继续解析
+    }
+    
+    if (parser->state == WS_STATE_COMPLETE) {
+        WS_LOGI(" WS_STATE_COMPLETE at %d\n",total_processed);
+    } else if (parser->state == WS_STATE_ERROR) {
+        WS_LOGI(" WS_STATE_ERROR at %d\n",total_processed);
+    } else {
+        // 数据不完整,继续等待更多数据
+        WS_LOGI("WS: Frame parsing incomplete, waiting for more data. State: %d, Buffer: %zu/%d, Payload remaining: %zu", 
+                parser->state, parser->buffer_pos, WS_BUFFER_SIZE, parser->payload_remaining);
+    }
+    return total_processed;
+}
+
+// 获取解析出的头部信息
+const ws_header_t* ws_get_header(ws_parser_t* parser) {
+    if (!parser || parser->state != WS_STATE_COMPLETE) {
+        return NULL;
+    }
+    return &parser->header;
+}
+
+// 获取完整数据包(包含帧头)
+const uint8_t* ws_get_packet(ws_parser_t* parser) {
+    if (!parser || parser->state != WS_STATE_COMPLETE) {
+        return NULL;
+    }
+    return parser->buffer;
+}
+
+// 获取纯载荷数据
+const uint8_t* ws_get_payload(ws_parser_t* parser) {
+    if (!parser || parser->state != WS_STATE_COMPLETE) {
+        return NULL;
+    }
+    
+    // 计算载荷数据的起始位置
+    // 帧头:2字节(基本头部)
+    size_t header_size = 2;
+    
+    // 扩展长度字段
+    if (parser->header.payload_len == 126) {
+        header_size += 2; // 16位长度
+    } else if (parser->header.payload_len == 127) {
+        header_size += 8; // 64位长度
+    }
+    
+    // 掩码密钥
+    if (parser->header.mask) {
+        header_size += 4;
+    }
+    
+    // 检查载荷数据是否在缓存范围内
+    if (header_size + parser->header.payload_len > parser->buffer_pos) {
+        WS_LOGE("WS: Payload start position %zu exceeds buffer size %zu", header_size, parser->buffer_pos);
+        return NULL;
+    }
+    
+    return parser->buffer + header_size;
+}
+
+// 获取载荷数据长度
+size_t ws_get_payload_length(ws_parser_t* parser) {
+    if (!parser || parser->state != WS_STATE_COMPLETE) {
+        return 0;
+    }
+    return parser->header.payload_len;
+}
+
+// 检查解析器是否有错误
+int ws_parser_has_error(ws_parser_t* parser) {
+    return (parser && parser->state == WS_STATE_ERROR) ? 1 : 0;
+}
+
+// 获取解析器当前状态
+ws_parse_state_t ws_parser_get_state(ws_parser_t* parser) {
+    return parser ? parser->state : WS_STATE_ERROR;
+}
+
+// 销毁解析器
+void ws_parser_destroy(ws_parser_t* parser) {
+    if (parser) {
+        free(parser);
+        g_parser_count--;
+        
+        // 如果所有解析器都被销毁,释放全局缓存
+        if (g_parser_count == 0 && g_ws_buffer) {
+            free(g_ws_buffer);
+            g_ws_buffer = NULL;
+            WS_LOGI("WS: Global buffer freed");
+        }
+        
+        WS_LOGI("WS: Parser destroyed, remaining parsers: %d", g_parser_count);
+    }
+}
+
+#ifdef __cplusplus
+}
+#endif
+#if 1
+// 多包拆解测试函数
+void test_multiple_frames() {
+    printf("\n=== Multiple WebSocket Frames Test ===\n");
+    
+    // 测试数据:包含多个WebSocket帧
+    uint8_t test_data[] = {
+        // 第一个帧:5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第二个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 BF 99 E6 A0 B7 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0xBF,
+        0x99, 0xE6, 0xA0, 0xB7, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A,
+        0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F,
+        0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第三个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E7 9A 84 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 74, 0x22, 0x3A, 0x22, 0xE7, 0x9A,
+        0x84, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C,
+        0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65,
+        0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第四个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 95 B0 E5 AD 97 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE6, 0x95,
+        0xB0, 0xE5, 0xAD, 0x97, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A,
+        0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F,
+        0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第五个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E7 BB 84 E5 90 88 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE7, 0xBB,
+        0x84, 0xE5, 0x90, 0x88, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A,
+        0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F,
+        0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第六个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 91 A2 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE5, 0x91,
+        0xA2, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C,
+        0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65,
+        0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第七个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E3 80 82 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE3, 0x80,
+        0x82, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C,
+        0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65,
+        0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第八个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E4 BD A0 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE4, 0xBD,
+        0xA0, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C,
+        0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65,
+        0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第九个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 83 BD 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0x83,
+        0xBD, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C,
+        0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65,
+        0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第十个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 AF B4 E8 AF B4 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0xAF,
+        0xB4, 0xE8, 0xAF, 0xB4, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A,
+        0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F,
+        0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第十一个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 BF 99 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0xBF,
+        0x99, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C,
+        0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65,
+        0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第十二个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 87 A0 E4 B8 AA 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE5, 0x87,
+        0xA0, 0xE4, 0xB8, 0xAA, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A,
+        0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F,
+        0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第十三个帧:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 95 B0 E5 AD 97 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE6, 0x95,
+        0xB0, 0xE5, 0xAD, 0x97, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A,
+        0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F,
+        0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第十四个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E6 98 AF 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE6, 0x98,
+        0xAF, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C,
+        0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65,
+        0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D,
+        
+        // 第十五个帧:82 45 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E5 9C A8 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+        0x82, 0x45, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+        0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE5, 0x9C,
+        0xA8, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C,
+        0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65,
+        0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D
+    };
+    
+    size_t test_data_len = sizeof(test_data);
+    
+    printf("Test data length: %zu bytes\n", test_data_len);
+    printf("Test data (hex): ");
+    for (size_t i = 0; i < test_data_len; i++) {
+        printf("%02X ", test_data[i]);
+        if ((i + 1) % 16 == 0) printf("\n                    ");
+    }
+    printf("\n");
+    
+    // 创建解析器
+    ws_parser_t* parser = ws_parser_init();
+    if (!parser) {
+        printf("Failed to create parser\n");
+        return;
+    }
+    
+    // 多包拆解测试
+    printf("\n=== Starting Multi-Frame Parsing ===\n");
+    
+    size_t offset = 0;
+    int frame_count = 0;
+    
+    while (offset < test_data_len) {
+        printf("\n--- Frame %d ---\n", frame_count + 1);
+        printf("Remaining data: %zu bytes\n", test_data_len - offset);
+        
+        // 解析当前帧
+        int result = ws_parse_stream(parser, test_data + offset, test_data_len - offset);
+        ws_parse_state_t ws_state = ws_parser_get_state(parser);
+        printf("ws_state: %d,result: %d\n", ws_state,result);
+        if (result > 0 && ws_state == WS_STATE_COMPLETE) {
+            frame_count++;
+            printf("Frame %d parsed successfully, consumed %d bytes\n", frame_count, result);
+            
+            const ws_header_t* header = ws_get_header(parser);
+            if (header) {
+                printf("Frame header:\n");
+                printf("  FIN: %d\n", header->fin);
+                printf("  RSV: %d%d%d\n", header->rsv1, header->rsv2, header->rsv3);
+                printf("  Opcode: 0x%02X\n", header->opcode);
+                printf("  Mask: %d\n", header->mask);
+                printf("  Payload length: %llu\n", (unsigned long long)header->payload_len);
+                
+                if (header->mask) {
+                    printf("  Mask key: 0x%02X%02X%02X%02X\n", 
+                        header->mask_key[0], header->mask_key[1], 
+                        header->mask_key[2], header->mask_key[3]);
+                }
+            }
+            
+            const uint8_t* payload = ws_get_payload(parser);
+            size_t payload_len = ws_get_payload_length(parser);
+            
+            if (payload && payload_len > 0) {
+                printf("Payload data:\n");
+                printf("  Length: %zu bytes\n", payload_len);
+                printf("  Hex: ");
+                for (size_t i = 0; i < payload_len && i < 32; i++) {
+                    printf("%02X ", payload[i]);
+                    if ((i + 1) % 16 == 0) printf("\n        ");
+                }
+                if (payload_len > 32) printf("...");
+                printf("\n");
+                
+                printf("  ASCII: ");
+                for (size_t i = 0; i < payload_len && i < 64; i++) {
+                    if (payload[i] >= 32 && payload[i] <= 126) {
+                        printf("%c", payload[i]);
+                    } else {
+                        printf(".");
+                    }
+                }
+                if (payload_len > 64) printf("...");
+                printf("\n");
+            }
+            
+            
+            
+            // 重置解析器状态,准备解析下一个帧
+            ws_parser_reset(parser);
+            
+        } else if (result > 0 && ws_state != WS_STATE_ERROR) {
+            printf("Parser state: %d reset \n", ws_parser_get_state(parser));
+            // 重置解析器状态,准备解析下一个帧
+            ws_parser_reset(parser);
+        } else {
+            printf("Incomplete frame, need more data\n");
+            // printf("Parse error at offset %zu\n", offset);
+            // printf("Parser state: %d\n", ws_parser_get_state(parser));
+        }
+
+        // 移动到下一个帧
+        offset += result;
+        // 添加安全检查
+        if (offset >= test_data_len) {
+            printf("Reached end of data\n");
+            break;
+        }
+    }
+    
+    printf("\n=== Multi-Frame Parsing Complete ===\n");
+    printf("Total frames parsed: %d\n", frame_count);
+    printf("Total bytes processed: %zu\n", offset);
+    printf("Remaining bytes: %zu\n", test_data_len - offset);
+    
+    // 清理
+    ws_parser_destroy(parser);
+}
+
+// 单帧测试函数(保留原有功能)
+void test_single_frame() {
+    printf("\n=== Single WebSocket Frame Test ===\n");
+    
+    // 测试数据:82 48 7B 22 74 79 70 65 22 3A 22 6D 69 64 64 6C 65 22 2C 22 63 6F 6E 74 65 6E 74 22 3A 22 E8 BF 99 E6 A0 B7 22 2C 22 74 61 73 6B 5F 69 64 22 3A 22 22 2C 22 72 65 61 73 6F 6E 69 6E 67 5F 63 6F 6E 74 65 6E 74 22 3A 22 22 7D
+
+    // 测试数据:WebSocket帧
+uint8_t test_data[] = {
+    // WebSocket帧头: 81 7E (FIN=1, Opcode=1, Mask=0, PayloadLen=126)
+    0x81, 0x7E,
+    
+    // 扩展长度: 00 BB (187字节)
+    0x00, 0xBB,
+    
+    // 负载数据开始: 7B 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30
+    0x7B, 0x22, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x3A, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+    
+    // 继续负载数据: 2C 22 6D 73 67 22 3A 22 73 75 63 63 65 73 73 22
+    0x2C, 0x22, 0x6D, 0x73, 0x67, 0x22, 0x3A, 0x22, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22,
+    
+    // 继续负载数据: 2C 22 74 61 73 6B 5F 69 64 22 3A 22 34 63 64 39 35
+    0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x34, 0x63, 0x64, 0x39, 0x35,
+    
+    // 继续负载数据: 62 62 39 35 63 37 35 39 32 65 38 38 31 31 63 37
+    0x62, 0x62, 0x39, 0x35, 0x63, 0x37, 0x35, 0x39, 0x32, 0x65, 0x38, 0x38, 0x31, 0x31, 0x63, 0x37,
+    
+    // 继续负载数据: 65 37 65 36 64 33 36 65 39 32 35 22 2C 22 65 76
+    0x65, 0x37, 0x65, 0x36, 0x64, 0x33, 0x36, 0x65, 0x39, 0x32, 0x35, 0x22, 0x2C, 0x22, 0x65, 0x76,
+    
+    // 继续负载数据: 65 6E 74 22 3A 22 43 68 61 6E 67 65 64 22 2C 22
+    0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x43, 0x68, 0x61, 0x6E, 0x67, 0x65, 0x64, 0x22, 0x2C, 0x22,
+    
+    // 继续负载数据: 72 65 73 75 6C 74 22 3A 7B 22 72 65 73 75 6C 74
+    0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x22, 0x3A, 0x7B, 0x22, 0x72, 0x65, 0x73, 0x75, 0x6C, 0x74,
+    
+    // 继续负载数据: 22 3A 22 E4 BD A0 EF BC 8C 22 2C 22 69 73 5F 65
+    0x22, 0x3A, 0x22, 0xE4, 0xBD, 0xA0, 0xEF, 0xBC, 0x8C, 0x22, 0x2C, 0x22, 0x69, 0x73, 0x5F, 0x65,
+    
+    // 继续负载数据: 6E 64 22 3A 66 61 6C 73 65 2C 22 73 65 6E 74 65
+    0x6E, 0x64, 0x22, 0x3A, 0x66, 0x61, 0x6C, 0x73, 0x65, 0x22, 0x2C, 0x22, 0x73, 0x65, 0x6E, 0x74,
+    
+    // 继续负载数据: 6E 63 65 5F 69 64 22 3A 22 22 2C 22 73 74 61 72
+    0x6E, 0x63, 0x65, 0x5F, 0x69, 0x64, 0x22, 0x3A, 0x22, 0x22, 0x2C, 0x22, 0x73, 0x74, 0x61, 0x72,
+    
+    // 继续负载数据: 74 5F 74 69 6D 65 22 3A 30 2C 22 65 6E 64 5F 74
+    0x74, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x22, 0x3A, 0x30, 0x22, 0x2C, 0x22, 0x65, 0x6E, 0x64, 0x5F, 0x74,
+    
+    // 继续负载数据: 69 6D 65 22 3A 30 7D 7D
+    0x69, 0x6D, 0x65, 0x22, 0x3A, 0x30, 0x7D, 0x7D
+};
+    // uint8_t test_data[] = {
+    //     0x82, 0x48, 0x7B, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3A, 0x22, 0x6D, 0x69, 0x64, 0x64, 0x6C,
+    //     0x65, 0x22, 0x2C, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0xE8, 0xBF,
+    //     0x99, 0xE6, 0xA0, 0xB7, 0x22, 0x2C, 0x22, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x22, 0x3A,
+    //     0x22, 0x22, 0x2C, 0x22, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x5F, 0x63, 0x6F,
+    //     0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x22, 0x7D
+    // };
+    
+    size_t test_data_len = sizeof(test_data);
+    
+    printf("Test data length: %zu bytes\n", test_data_len);
+    printf("Test data (hex): ");
+    for (size_t i = 0; i < test_data_len; i++) {
+        printf("%02X ", test_data[i]);
+        if ((i + 1) % 16 == 0) printf("\n                    ");
+    }
+    printf("\n");
+    
+    // 创建解析器
+    ws_parser_t* parser = ws_parser_init();
+    if (!parser) {
+        printf("Failed to create parser\n");
+        return;
+    }
+    
+    // 解析数据
+    int result = ws_parse_stream(parser, test_data, test_data_len);
+    
+    if (result > 0) {
+        printf("\n=== Parse Result ===\n");
+        printf("Parsed bytes: %d\n", result);
+        
+        const ws_header_t* header = ws_get_header(parser);
+        if (header) {
+            printf("Frame header:\n");
+            printf("  FIN: %d\n", header->fin);
+            printf("  RSV: %d%d%d\n", header->rsv1, header->rsv2, header->rsv3);
+            printf("  Opcode: 0x%02X\n", header->opcode);
+            printf("  Mask: %d\n", header->mask);
+            printf("  Payload length: %llu\n", (unsigned long long)header->payload_len);
+            
+            if (header->mask) {
+                printf("  Mask key: 0x%02X%02X%02X%02X\n", 
+                    header->mask_key[0], header->mask_key[1], 
+                    header->mask_key[2], header->mask_key[3]);
+            }
+        }
+        
+        const uint8_t* payload = ws_get_payload(parser);
+        size_t payload_len = ws_get_payload_length(parser);
+        
+        if (payload && payload_len > 0) {
+            printf("\nPayload data:\n");
+            printf("  Length: %zu bytes\n", payload_len);
+            printf("  Hex: ");
+            for (size_t i = 0; i < payload_len && i < 64; i++) {
+                printf("%02X ", payload[i]);
+                if ((i + 1) % 16 == 0) printf("\n        ");
+            }
+            if (payload_len > 64) printf("...");
+            printf("\n");
+            
+            printf("  ASCII: ");
+            for (size_t i = 0; i < payload_len && i < 64; i++) {
+                if (payload[i] >= 32 && payload[i] <= 126) {
+                    printf("%c", payload[i]);
+                } else {
+                    printf(".");
+                }
+            }
+            if (payload_len > 64) printf("...");
+            printf("\n");
+        }
+        
+        printf("\nParser state: %d\n", ws_parser_get_state(parser));
+        
+    } else if (result == 0) {
+        printf("Incomplete frame, need more data\n");
+        printf("Parser state: %d\n", ws_parser_get_state(parser));
+    } else {
+        printf("Parse error\n");
+        printf("Parser state: %d\n", ws_parser_get_state(parser));
+    }
+    
+    // 清理
+    ws_parser_destroy(parser);
+}
+
+int main() {
+    printf("WebSocket Parser Standalone Test\n");
+    printf("================================\n");
+    
+    // 测试单帧解析
+    test_single_frame();
+    
+    // 测试多帧解析
+    test_multiple_frames();
+    
+    printf("\nAll tests completed.\n");
+    return 0;
+}
+
+#endif
\ No newline at end of file
diff --git a/test_ws_parser/websocket_simple_analysis.json b/test_ws_parser/websocket_simple_analysis.json
new file mode 100644 (file)
index 0000000..daf483f
--- /dev/null
@@ -0,0 +1,163 @@
+{
+  "summary": {
+    "total_frames": 9,
+    "total_bytes": 503,
+    "valid_frames": 9,
+    "skipped_frames": 494
+  },
+  "frames": [
+    {
+      "frame_index": 0,
+      "offset": 0,
+      "header": {
+        "fin": 1,
+        "rsv": 3,
+        "rsv_binary": "011",
+        "opcode": "0x02",
+        "opcode_name": "BINARY",
+        "mask": 1,
+        "payload_length": 75
+      },
+      "frame_size": 81,
+      "payload_hex": "B2 CB 2C 65 94 15 47 92 C0 60 81 84 0E 08 10 50 C0 E5 96 4F FF F9 67 FF CB 2C A9 60 60 A0 81 CA 8F 21 91 91 97 FF FF FF C4 64 65 E4 65 FF E6 46 73 23 23 23 32 32 32 32 1F FF F3 23 76 76 76 76 79 38 D3 8B 28 B3 0F 2D A4 E2 CA",
+      "payload_utf8": ",e\u0015G`\u000e\b\u0010POg,``ʏ!deeFs###2222\u001f#vvvvy8Ӌ(\u000f-",
+      "payload_json": null
+    },
+    {
+      "frame_index": 1,
+      "offset": 95,
+      "header": {
+        "fin": 0,
+        "rsv": 3,
+        "rsv_binary": "011",
+        "opcode": "0x08",
+        "opcode_name": "CLOSE",
+        "mask": 1,
+        "payload_length": 50
+      },
+      "frame_size": 56,
+      "payload_hex": "F3 48 C4 DF 18 BB F2 14 F4 28 45 5D 4E 34 E2 CA 3C C0 3A 4C 41 4D 45 33 2E 31 30 30 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA",
+      "payload_utf8": "H\u0018\u0014(E]N4<:LAME3.100",
+      "payload_json": null
+    },
+    {
+      "frame_index": 2,
+      "offset": 151,
+      "header": {
+        "fin": 1,
+        "rsv": 2,
+        "rsv_binary": "010",
+        "opcode": "0x0A",
+        "opcode_name": "PONG",
+        "mask": 1,
+        "payload_length": 42
+      },
+      "frame_size": 48,
+      "payload_hex": "AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA",
+      "payload_utf8": "",
+      "payload_json": null
+    },
+    {
+      "frame_index": 3,
+      "offset": 199,
+      "header": {
+        "fin": 1,
+        "rsv": 2,
+        "rsv_binary": "010",
+        "opcode": "0x0A",
+        "opcode_name": "PONG",
+        "mask": 1,
+        "payload_length": 42
+      },
+      "frame_size": 48,
+      "payload_hex": "AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA FF F3 48",
+      "payload_utf8": "H",
+      "payload_json": null
+    },
+    {
+      "frame_index": 4,
+      "offset": 252,
+      "header": {
+        "fin": 1,
+        "rsv": 7,
+        "rsv_binary": "111",
+        "opcode": "0x08",
+        "opcode_name": "CLOSE",
+        "mask": 0,
+        "payload_length": 52
+      },
+      "frame_size": 54,
+      "payload_hex": "18 4D CC AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA",
+      "payload_utf8": "\u0018M̪",
+      "payload_json": null
+    },
+    {
+      "frame_index": 5,
+      "offset": 306,
+      "header": {
+        "fin": 1,
+        "rsv": 2,
+        "rsv_binary": "010",
+        "opcode": "0x0A",
+        "opcode_name": "PONG",
+        "mask": 1,
+        "payload_length": 42
+      },
+      "frame_size": 48,
+      "payload_hex": "AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA",
+      "payload_utf8": "",
+      "payload_json": null
+    },
+    {
+      "frame_index": 6,
+      "offset": 354,
+      "header": {
+        "fin": 1,
+        "rsv": 2,
+        "rsv_binary": "010",
+        "opcode": "0x0A",
+        "opcode_name": "PONG",
+        "mask": 1,
+        "payload_length": 42
+      },
+      "frame_size": 48,
+      "payload_hex": "AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 81 72 7B 22 68 65 61 64 65 72 22 3A 7B 22",
+      "payload_utf8": "r{\"header\":{\"",
+      "payload_json": null
+    },
+    {
+      "frame_index": 7,
+      "offset": 407,
+      "header": {
+        "fin": 0,
+        "rsv": 2,
+        "rsv_binary": "010",
+        "opcode": "0x02",
+        "opcode_name": "BINARY",
+        "mask": 0,
+        "payload_length": 58
+      },
+      "frame_size": 60,
+      "payload_hex": "22 45 6E 64 53 79 6E 74 68 65 73 69 73 22 2C 22 6D 73 67 22 3A 22 73 75 63 63 65 73 73 22 2C 22 73 74 61 74 75 73 22 3A 32 30 30 30 30 30 30 30 2C 22 74 61 73 6B 5F 69 64 22",
+      "payload_utf8": "\"EndSynthesis\",\"msg\":\"success\",\"status\":20000000,\"task_id\"",
+      "payload_json": null
+    },
+    {
+      "frame_index": 8,
+      "offset": 467,
+      "header": {
+        "fin": 0,
+        "rsv": 3,
+        "rsv_binary": "011",
+        "opcode": "0x0A",
+        "opcode_name": "PONG",
+        "mask": 0,
+        "payload_length": 34
+      },
+      "frame_size": 36,
+      "payload_hex": "37 63 30 31 36 37 61 63 63 30 61 37 32 31 38 37 65 33 64 61 31 31 39 61 36 61 35 61 62 62 33 30 22 7D",
+      "payload_utf8": "7c0167acc0a72187e3da119a6a5abb30\"}",
+      "payload_json": null
+    }
+  ]
+}
\ No newline at end of file
diff --git a/test_ws_parser/websocket_simple_analysis.py b/test_ws_parser/websocket_simple_analysis.py
new file mode 100644 (file)
index 0000000..f843774
--- /dev/null
@@ -0,0 +1,200 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+简化版WebSocket数据解析工具 - 增强版,确保RSV位验证
+"""
+
+import json
+import re
+
+def hex_to_bytes(hex_string):
+    """将十六进制字符串转换为字节"""
+    hex_string = re.sub(r'\s+', '', hex_string)
+    return bytes.fromhex(hex_string)
+
+def get_opcode_name(opcode):
+    """获取操作码名称"""
+    opcode_names = {
+        0x0: "CONTINUATION",
+        0x1: "TEXT",
+        0x2: "BINARY",
+        0x8: "CLOSE",
+        0x9: "PING",
+        0xA: "PONG"
+    }
+    return opcode_names.get(opcode, f"UNKNOWN(0x{opcode:02X})")
+
+def analyze_websocket_frames(hex_data):
+    """分析WebSocket帧,确保只有RSV位为0的帧才有效"""
+    data = hex_data
+    frames = []
+    offset = 0
+    skipped_count = 0
+    
+    print(f"开始分析WebSocket数据,总长度: {len(data)} 字节")
+    
+    while offset < len(data):
+        if offset + 2 > len(data):
+            break
+            
+        # 解析帧头
+        first_byte = data[offset]
+        second_byte = data[offset + 1]
+        
+        fin = (first_byte >> 7) & 0x1
+        rsv = (first_byte >> 4) & 0x7
+        opcode = first_byte & 0x0F
+        mask = (second_byte >> 7) & 0x1
+        payload_len = second_byte & 0x7F
+        
+        # 验证RSV位 - 只有RSV为0的帧才有效
+        # if rsv != 0:
+        #     print(f"跳过无效帧: 偏移={offset}, RSV={rsv:03b} (非0), 第一个字节=0x{first_byte:02X}")
+        #     offset += 1  # 跳过1字节,继续搜索
+        #     skipped_count += 1
+        #     continue
+        
+        # 验证操作码是否有效
+        valid_opcodes = [0x0, 0x1, 0x2, 0x8, 0x9, 0xA]  # CONTINUATION, TEXT, BINARY, CLOSE, PING, PONG
+        if opcode not in valid_opcodes:
+            print(f"跳过无效帧: 偏移={offset}, 操作码=0x{opcode:02X} (无效), 第一个字节=0x{first_byte:02X}")
+            offset += 1  # 跳过1字节,继续搜索
+            skipped_count += 1
+            continue
+        
+        # 计算帧头大小
+        header_size = 2
+        if payload_len == 126:
+            if offset + 4 <= len(data):
+                extended_len = int.from_bytes(data[offset+2:offset+4], 'big')
+                header_size += 2
+            else:
+                extended_len = 0
+        elif payload_len == 127:
+            if offset + 10 <= len(data):
+                extended_len = int.from_bytes(data[offset+2:offset+10], 'big')
+                header_size += 8
+            else:
+                extended_len = 0
+        else:
+            extended_len = payload_len
+            
+        if mask:
+            header_size += 4
+            
+        total_frame_size = header_size + extended_len
+        
+        if offset + total_frame_size > len(data):
+            break
+            
+        # 提取负载
+        payload_start = offset + header_size
+        payload_data = data[payload_start:payload_start + extended_len]
+        
+        # 尝试解析JSON
+        json_content = None
+        try:
+            if payload_data:
+                json_content = json.loads(payload_data.decode('utf-8'))
+        except:
+            pass
+            
+        # 构建帧信息
+        frame_info = {
+            "frame_index": len(frames),
+            "offset": offset,
+            "header": {
+                "fin": fin,
+                "rsv": rsv,
+                "rsv_binary": f"{rsv:03b}",  # 添加二进制表示
+                "opcode": f"0x{opcode:02X}",
+                "opcode_name": get_opcode_name(opcode),  # 添加操作码名称
+                "mask": mask,
+                "payload_length": extended_len
+            },
+            "frame_size": total_frame_size,
+            "payload_hex": payload_data.hex(' ').upper() if payload_data else "",
+            "payload_utf8": payload_data.decode('utf-8', errors='ignore') if payload_data else "",
+            "payload_json": json_content
+        }
+        
+        frames.append(frame_info)
+        print(f"发现有效帧: 偏移={offset}, 操作码={get_opcode_name(opcode)}, 大小={total_frame_size}字节, RSV={rsv:03b}")
+        offset += total_frame_size
+    
+    print(f"分析完成: 有效帧={len(frames)}, 跳过帧={skipped_count}")
+    return frames
+
+def main():
+    # 原始十六进制数据
+    hex_data = """B2 CB 25 96 59 64 B2 CB 2C 65 94 15 47 92 C0 60 
+                    81 84 0E 08 10 50 C0 E5 96 4F FF F9 67 FF CB 2C 
+                    A9 60 60 A0 81 CA 8F 21 91 91 97 FF FF FF C4 64 
+                    65 E4 65 FF E6 46 73 23 23 23 32 32 32 32 1F FF 
+                    F3 23 76 76 76 76 79 38 D3 8B 28 B3 0F 2D A4 E2 
+                    CA 2C C3 DD A6 9D 9C C3 DD 9D 9D 9D 9C D3 8D 38 
+                    B2 8B 28 B3 FF F3 48 C4 DF 18 BB F2 14 F4 28 45 
+                    5D 4E 34 E2 CA 3C C0 3A 4C 41 4D 45 33 2E 31 30 
+                    30 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
+                    AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
+                    AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
+                    AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
+                    AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
+                    AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
+                    AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
+                    AA AA AA AA FF F3 48 C4 EF 1C A4 14 F8 34 18 4D 
+                    CC AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
+                    AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
+                    AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
+                    AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
+                    AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
+                    AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
+                    AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
+                    AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
+                    AA AA AA AA 81 72 7B 22 68 65 61 64 65 72 22 3A 
+                    7B 22 65 76 65 6E 74 22 3A 22 45 6E 64 53 79 6E 
+                    74 68 65 73 69 73 22 2C 22 6D 73 67 22 3A 22 73 
+                    75 63 63 65 73 73 22 2C 22 73 74 61 74 75 73 22 
+                    3A 32 30 30 30 30 30 30 30 2C 22 74 61 73 6B 5F 
+                    69 64 22 3A 22 37 63 30 31 36 37 61 63 63 30 61 
+                    37 32 31 38 37 65 33 64 61 31 31 39 61 36 61 35 
+                    61 62 62 33 30 22 7D"""
+    
+    # 转换为字节
+    data = hex_to_bytes(hex_data)
+    
+    # 分析帧
+    frames = analyze_websocket_frames(data)
+    
+    # 生成输出
+    output = {
+        "summary": {
+            "total_frames": len(frames),
+            "total_bytes": len(data),
+            "valid_frames": len(frames),
+            "skipped_frames": len(data) - len(frames)  # 估算跳过的帧数
+        },
+        "frames": frames
+    }
+    
+    # 保存到文件
+    with open("websocket_simple_analysis.json", "w", encoding="utf-8") as f:
+        json.dump(output, f, ensure_ascii=False, indent=2)
+        
+    print(f"分析完成,共发现 {len(frames)} 个有效WebSocket帧")
+    print("结果已保存到 websocket_simple_analysis.json")
+    
+    # 打印前几个帧的摘要
+    for i, frame in enumerate(frames[:5]):
+        print(f"\n帧 {i+1}:")
+        print(f"  偏移: {frame['offset']}")
+        print(f"  大小: {frame['frame_size']} 字节")
+        print(f"  FIN: {frame['header']['fin']}")
+        print(f"  RSV: {frame['header']['rsv_binary']} ({frame['header']['rsv']})")
+        print(f"  操作码: {frame['header']['opcode']} ({frame['header']['opcode_name']})")
+        print(f"  负载长度: {frame['header']['payload_length']}")
+        if frame['payload_json']:
+            print(f"  JSON内容: {frame['payload_json']}")
+
+if __name__ == "__main__":
+    main()
\ No newline at end of file