执行 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.
我有以下代码作为 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.