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

TCP Server读取NetworkStream消息时被截断的问题解决

解决TCP监听器接收内容截断的问题

问题根源

你的代码存在两个核心问题导致内容截断:

  • 使用固定大小的toReceive(100000)字节数组,当请求内容(比如案例中Content-Length为106438)超过这个长度时,超出部分会直接丢失
  • 仅通过单次While ns.DataAvailable循环读取数据,TCP是流式传输,数据可能分多批次到达,单次循环无法保证读取完整内容

另外,直接通过字符串拆分text = "{" & text.Split("{")(1)提取JSON的方式非常脆弱,一旦HTTP头格式变化就会出错,应该先解析HTTP头获取Content-Length,再精准读取完整的JSON内容。

修复后的代码

Using client As TcpClient = _server.AcceptTcpClient()
    Threading.ThreadPool.QueueUserWorkItem(AddressOf NewClient)

    Using ns As NetworkStream = client.GetStream()
        ' 第一步:读取并解析HTTP请求头,提取Content-Length
        Dim headerBuilder As New StringBuilder()
        Dim buffer(1023) As Byte
        Dim bytesRead As Integer

        ' 读取HTTP头直到遇到空行(头与体的分隔标记)
        Do
            bytesRead = ns.Read(buffer, 0, buffer.Length)
            If bytesRead = 0 Then Exit Do

            headerBuilder.Append(Encoding.UTF8.GetString(buffer, 0, bytesRead))
            If headerBuilder.ToString().Contains(vbCrLf & vbCrLf) Then
                Exit Do
            End If
        Loop

        Dim headerText As String = headerBuilder.ToString()
        Dim contentLength As Integer = 0
        ' 提取Content-Length数值
        Dim contentLengthLine As String = headerText.Split(vbCrLf).FirstOrDefault(Function(line) line.StartsWith("Content-Length:"))
        If contentLengthLine IsNot Nothing Then
            Integer.TryParse(contentLengthLine.Split(":")(1).Trim(), contentLength)
        End If

        ' 第二步:根据Content-Length读取完整的JSON内容
        Dim jsonBytes As New List(Of Byte)()
        Dim totalRead As Integer = 0

        While totalRead < contentLength AndAlso ns.CanRead
            ' 计算剩余需读取的字节,用4096大小的缓冲区平衡效率与内存占用
            Dim remaining = contentLength - totalRead
            Dim readBufferSize = Math.Min(4096, remaining)
            Dim readBuffer(readBufferSize - 1) As Byte

            bytesRead = ns.Read(readBuffer, 0, readBufferSize)
            If bytesRead = 0 Then Exit Loop

            jsonBytes.AddRange(readBuffer.Take(bytesRead))
            totalRead += bytesRead
        End While

        ' 处理完整的JSON数据
        If totalRead >= My.Settings.minLenghtForSuccess Then
            Dim jsonText As String = Encoding.UTF8.GetString(jsonBytes.ToArray())
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonText)
            
            Dim ipOrigine As String = jsonObj("data")("IPAddress")
            Dim dispositivoOrigine As String = jsonObj("data")("DeviceName")
            Dim canaleOrigine As String = jsonObj("data")("ChannelName")
            Dim targa As String = jsonObj("data")("PicData")("PlateInfo")(0)("SnapId")

            ' 这里添加你的业务逻辑处理代码
        End If
    End Using
End Using

关键改动说明

  • HTTP头解析:先读取完整的HTTP请求头,明确获取Content-Length字段的值,知道需要读取的JSON内容总长度
  • 动态缓冲区:使用List(Of Byte)累积读取的字节,彻底摆脱固定大小数组的限制
  • 分批次读取:循环读取直到获取到Content-Length指定的所有字节,适配TCP流式传输的特性,确保数据完整
  • 严谨的JSON解析:直接使用读取到的完整JSON字符串解析,避免了原代码中脆弱的字符串拆分逻辑

内容的提问来源于stack exchange,提问作者Gabriele Cozzolino

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 22:26:00