C#/.NET解析WebSocket数据时Decimal值不正确如何修复
问题原因
你的解析逻辑存在3个核心缺陷,才会出现数值解析错误:
- 多余序列化操作:对WebSocket原始接收数据调用
JsonConvert.SerializeObject会额外引入转义符、包裹引号,无意义增加解析干扰。 - 未处理TCP粘包/半包问题:WebSocket基于TCP传输,收到的数据片段可能是不完整的半帧、或者多帧拼接的内容,你拿到片段就直接按逗号拆分,很容易拿到截断的字段:比如
ltp:16201.8被截断成ltp:162018(小数点在后续分片里),或者上一帧尾部的165.0和当前帧的ltp:18粘在一起,就会解析出错误值。 - 字段匹配逻辑错误:用
Contains("ltp")做模糊匹配,会把粘包后混了其他内容、但包含ltp子串的脏片段当成目标字段,再加上Split(':')取最后一段的逻辑没有校验键名,很容易取到错误的值。
修复方案
- 新增接收缓冲区,每次收到WebSocket数据先拼到缓冲区,校验凑出完整合法的数据帧(首尾为
"、结构完整)之后再做解析,不处理分片残片。 - 移除多余的
JsonConvert.SerializeObject逻辑,直接处理拼接完成的原始完整帧。 - 拆分键值对后精确匹配键名等于
ltp的项,再做数值转换,同时用decimal.TryParse做合法性校验,避免脏数据导致转换异常。
修复后的参考代码:
// 类级别接收缓冲区,用于拼接WebSocket分片 private string _wsReceiveBuffer = string.Empty; /// <summary> /// 每次收到WebSocket消息时触发该处理方法 /// </summary> /// <param name="receivedChunk">单次收到的数据片段</param> void HandleWebSocketReceive(string receivedChunk) { // 新收到的片段拼到缓冲区 _wsReceiveBuffer += receivedChunk; // 循环提取缓冲区中所有完整的数据帧 while (true) { // 查找帧起始位置(双引号) int frameStart = _wsReceiveBuffer.IndexOf('"'); if (frameStart == -1) { // 无合法帧头,清空脏数据 _wsReceiveBuffer = string.Empty; break; } // 查找对应帧尾位置 int frameEnd = _wsReceiveBuffer.IndexOf('"', frameStart + 1); if (frameEnd == -1) { // 未凑齐完整帧,保留有效部分等待后续分片,退出循环 _wsReceiveBuffer = _wsReceiveBuffer.Substring(frameStart); break; } // 提取完整帧内容,移除首尾自带的双引号 string completeDataFrame = _wsReceiveBuffer.Substring(frameStart + 1, frameEnd - frameStart - 1); // 已处理的内容从缓冲区移除 _wsReceiveBuffer = _wsReceiveBuffer.Substring(frameEnd + 1); // 解析ltp字段 decimal ltpValue = 0m; string[] keyValueItems = completeDataFrame.Split(','); foreach (string item in keyValueItems) { string[] keyAndValue = item.Split(':'); // 精确匹配ltp键,且值格式合法 if (keyAndValue.Length == 2 && keyAndValue[0] == "ltp" && decimal.TryParse(keyAndValue[1], out ltpValue)) { break; } } // 此处ltpValue即为正确解析的数值,可用于后续业务逻辑 } }
内容的提问来源于stack exchange,提问作者harsh
相关产品推荐
相关产品推荐

