You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#/.NET解析WebSocket数据时Decimal值不正确如何修复

问题原因

你的解析逻辑存在3个核心缺陷,才会出现数值解析错误:

  1. 多余序列化操作:对WebSocket原始接收数据调用JsonConvert.SerializeObject会额外引入转义符、包裹引号,无意义增加解析干扰。
  2. 未处理TCP粘包/半包问题:WebSocket基于TCP传输,收到的数据片段可能是不完整的半帧、或者多帧拼接的内容,你拿到片段就直接按逗号拆分,很容易拿到截断的字段:比如ltp:16201.8被截断成ltp:162018(小数点在后续分片里),或者上一帧尾部的165.0和当前帧的ltp:18粘在一起,就会解析出错误值。
  3. 字段匹配逻辑错误:用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 15:00:55