首页 > 解决方案 > Visual Basic TCP 数据损坏

问题描述

我有一个程序使用 TCP 进行客户端和服务器之间的通信。客户端发送一个 BMP 图像的字节数组。侦听器以块的形式读取字节并将字节连接在一起以获取图像。当服务器/侦听器接收到图像时,它几乎在中途损坏。

当使用 localhost 在我的计算机上进行测试时,损坏的可能性较小(更大的字节数组大小 = 更多的损坏),但是当通过互联网时,无论大小如何,它都有 99% 的时间被损坏。我也尝试过拆分字节数组并将其分块发送到服务器,这似乎修复了本地主机上的损坏,但在互联网上仍然相同。

有人可以告诉我我在这里做错了什么吗?

在计时器中运行的监听器代码:

If Listener.Pending = True Then
Client = Listener.AcceptTcpClient()
Message = ""
Dim ClientNetworkStream As NetworkStream = Client.GetStream
ReDim ReadBytes(-1)
If ClientNetworkStream.CanRead = True Then
    Dim ReadBuffer(65535) As Byte
    Dim NumberOfBytesRead As Integer = 0
    Do
    NumberOfBytesRead = ClientNetworkStream.Read(ReadBuffer, 0, ReadBuffer.Length)
    If Not NumberOfBytesRead = 0 Then
        If Not NumberOfBytesRead = -1 Then
            ReadBytes = AppendByteArrays(ReadBytes, ReadBuffer, NumberOfBytesRead)
            If ConvoOngoing = False Then
            ReDim CurrentConvoBytes(-1)
            ConvoOngoing = True
            CurrentConvoBytes = ReadBytes
        Else
            CurrentConvoBytes = AppendByteArrays(CurrentConvoBytes, ReadBytes)
        End If
    End If
End If
Loop While ClientNetworkStream.DataAvailable
    If ClientNetworkStream.DataAvailable = False Then
        If ConvoOngoing = True Then
            If ReadBytes.Length > 0 Then
                CurrentConvoBytes = AppendByteArrays(CurrentConvoBytes, ReadBytes)
            End If
        ConvoOngoing = False
        PictureBox1.Image = ConvertByteArrayToBMP(CurrentConvoBytes)
        End If
    End If
End If
End If

这是发件人代码:

    Private Sub SendWhole(ByVal BytesToSend() As Byte, ByVal Optional isFile As Boolean = False)
    Client = New TcpClient(TextBox2.Text, TextBox3.Text)
    Dim ClientStream As NetworkStream = Client.GetStream
    ClientStream.Write(BytesToSend, 0, BytesToSend.Length)
    ClientStream.Close()
End Sub

以及代码中使用的 AppendByteArrays 代码:

    Public Function AppendByteArrays(ByVal OriginalArray As Byte(), ByVal ArrayToAppend As Byte(), ByVal Optional AmountOfValuesToAdd As Integer = -1) As Byte()
    Dim IndexToStart As Integer = OriginalArray.Length
    Dim Modifier As Integer = 0
    If Not AmountOfValuesToAdd = -1 Then
        Modifier = AmountOfValuesToAdd - 1
    Else
        Modifier = -1
    End If
    If Modifier = -1 Then
        ReDim Preserve OriginalArray((OriginalArray.Length) + (ArrayToAppend.Length - 1))
        For i = 0 To ArrayToAppend.Length - 1
            OriginalArray(IndexToStart + i) = ArrayToAppend(i)
        Next
    Else
        ReDim Preserve OriginalArray((OriginalArray.Length) + Modifier)
        For i = 0 To Modifier
            OriginalArray(IndexToStart + i) = ArrayToAppend(i)
        Next
    End If
    Return OriginalArray
End Function

编辑:这是我似乎无法弄清楚数学的地方

        If Listener.Pending = True Then
        Client = Listener.AcceptTcpClient()
        Dim ClientNetworkStream As NetworkStream = Client.GetStream
        ReDim ReadBytes(-1)
        If ClientNetworkStream.CanRead = True Then
            Dim ReadBuffer(65535) As Byte
            Dim NumberOfBytesRead As Integer = 0
            Do
                NumberOfBytesRead = ClientNetworkStream.Read(ReadBuffer, 0, ReadBuffer.Length)
                If Not NumberOfBytesRead = 0 Then
                    If Not NumberOfBytesRead = -1 Then
                        If ReadingPacket = False Then
                            If PacketHasLeftOvers = True Then
                                PacketHasLeftOvers = False
                                ReadBuffer = AppendByteArrays(PacketLeftOvers, ReadBuffer)
                                ReDim PacketLeftOvers(-1)
                            End If
                            ReadingPacket = True
                            PacketToReadSize = BitConverter.ToInt32(ReadBuffer, 0)
                            PacketType = ReadBuffer(4)
                            ReDim CurrentConvoBytes(-1)
                            ReadBytes = AppendByteArrays(ReadBytes, ReadBuffer.Skip(5).ToArray, NumberOfBytesRead - 5)
                            CurrentConvoBytes = ReadBytes
                            PacketReadSize = ReadBytes.Length - 1
                            If PacketReadSize = PacketToReadSize Then
                                'Check if already finished reading
                                PictureBox1.Image = ConvertByteArrayToBMP(CurrentConvoBytes)
                                PacketReadSize = 0
                                ReadingPacket = False
                            End If
                        Else
                            Dim PacketScore As Integer = PacketReadSize + NumberOfBytesRead
                            If PacketScore < PacketToReadSize Then
                                ReadBytes = AppendByteArrays(ReadBytes, ReadBuffer, NumberOfBytesRead)
                                CurrentConvoBytes = AppendByteArrays(CurrentConvoBytes, ReadBytes)
                                PacketReadSize += ReadBytes.Length - 1
                            ElseIf PacketScore > PacketToReadSize Then
                                ReadBytes = AppendByteArrays(ReadBytes, ReadBuffer, NumberOfBytesRead - (PacketToReadSize - PacketReadSize))
                                CurrentConvoBytes = AppendByteArrays(CurrentConvoBytes, ReadBytes)
                                PacketHasLeftOvers = True
                                PacketLeftOvers = ReadBuffer.Skip(PacketToReadSize - PacketReadSize).ToArray
                                PictureBox1.Image = ConvertByteArrayToBMP(CurrentConvoBytes)
                                PacketReadSize = 0
                                ReadingPacket = False
                            ElseIf PacketScore = PacketToReadSize Then
                                ReadBytes = AppendByteArrays(ReadBytes, ReadBuffer, NumberOfBytesRead)
                                CurrentConvoBytes = AppendByteArrays(CurrentConvoBytes, ReadBytes)
                                PictureBox1.Image = ConvertByteArrayToBMP(CurrentConvoBytes)
                                PacketReadSize = 0
                                ReadingPacket = False
                            End If
                        End If
                    End If
                Else
                    Throw New Exception
                End If
            Loop While ClientNetworkStream.DataAvailable
        End If
    End If

标签: vb.nettcpcorruptionnetworkstream

解决方案


推荐阅读