执行 GetStream.Read 时会发生什么?

What happen when GetStream.Read is executed?

我有以下代码作为 TCP 服务器的一部分

Private Sub StartTcpClient(ByVal client As TcpClient)

    Dim bytesRead As Integer
    Dim RxBuffer(1024) As Byte
    Dim RxDataStr As String = ""

    Dim BeginTime As Date = Date.Now
    Dim CurrentTime As Date
    Dim ElapsedTicks As Long = -1
    'Dim elapsedSpan As New TimeSpan(elapsedTicks)

    While True
        bytesRead = client.GetStream.Read(RxBuffer, 0, RxBuffer.Length)'What happen here?

        If bytesRead > 0 Or ElapsedTicks < 3 * 10000000.0 Then 'Espera hasta 3 segundos

            CurrentTime = Date.Now
            ElapsedTicks = CurrentTime.Ticks - BeginTime.Ticks
            'RxDataStr = System.Text.ASCIIEncoding.ASCII.GetString(RxBuffer, 0, bytesRead) 'Original
            RxDataStr += System.Text.ASCIIEncoding.Default.GetString(RxBuffer, 0, bytesRead) 'UTF8

        Else
            client.Close()
            AckString = RxDataStr
            AckReady = True
            AckPending = False
            Exit Sub
        End If
    End While
End Sub

我想知道执行 GetStream.Read 行时会发生什么。 它从我的代码中消失,直到收集到一些数据或发生错误或其他情况后才会返回?

如果数据到达之间的时间大于 3 秒,我需要做的是关闭当前连接。

您似乎正在尝试循环读取流,直到没有收到更多数据,或者自您开始读取以来已经过了一定时间。

您用来执行此操作的调用 Stream.Read 是阻塞调用。因此,如果您没有收到任何数据,此 将无限期阻塞

因为在您的情况下,您拥有的流实例是 NetworkStream,您可以指定其 ReadTimeout 属性 以防止这个。这会导致以下行为:

If the read operation does not complete within the time specified by this property, the read operation throws an IOException.

因此,您必须捕获 IOException 并检查它是否是由于读取超时造成的。您的代码将如下所示:

Imports System.Diagnostics

// ... other stuff

Dim stream As Stream = client.GetStream
Dim maxTime As TimeSpan = TimeSpan.FromSeconds(3)
Dim elapsed As Stopwatch = Stopwatch.StartNew()
Dim done As Boolean = False

While Not done
    Dim timeout As Long = CLng((maxTime - elapsed.Elapsed).TotalMilliseconds))
    If (timeout > 0) Then
        stream.ReadTimeout = timeout
        Try
            bytesRead = stream.Read(RxBuffer, 0, RxBuffer.Length)
            If bytesRead > 0 Then 'Espera hasta 3 segundos
                RxDataStr += System.Text.ASCIIEncoding.Default.GetString(RxBuffer, 0, bytesRead) 'UTF8
            Else
                done = True
            End If
        Catch ioEx As IOException
            If elapsed.Elapsed > maxTime Then
                done = True ' due to read timeout
            Else
                Throw ' not due to read timeout, rethrow
            End If
        End Try
    Else
        done = True
    End If
End While

client.Close()
AckString = RxDataStr
AckReady = True
AckPending = False

由于您正在执行 I/O,我还建议使用 async/await 和 Stream.ReadAsync 作为异步操作执行它。在这种情况下,您应该让调用链中的所有方法执行 async/await.