输入缓冲区在读取后不能可靠地清除
The input buffer does not reliably clear after reading
我正在编写一个小型串行代理,以便我可以窃听遗留应用程序和它打算控制的设备之间的对话。
我的计划是:
- 使用将串行数据包发送到 TCP 端口的虚拟串行端口拦截应用程序的命令
- 将这些命令中继到设备
- 将设备的响应中继回应用程序。
到目前为止,当我只使用我的测试命令时它工作可靠。但是,当我使用该应用程序启动通信时,它会间歇性地失败。显然,该应用程序通过网络发送 'wake-up ping' 以验证与设备的连接是否成功。 'ping' 作为单字节值 ChrW(3)
出现,设备响应 =>
(成功)。只要输入缓冲区在我尝试读取之前是清空的,它就可以正常工作。
那是断断续续的部分。有时 ChrW(3)
会卡在那里,有时不会。随后的调用只是堆积在它之上。另一方面,我的测试命令总是清除。好像就是那个低阶角色的问题。
这是我的代码,我认为非常简单:
Private Sub TcpClient()
Dim aData As Byte()
Dim _
sLogger,
sDevice As String
Dim _
iBytes,
iPort As Integer
sDevice = String.Empty
iPort = 5001
Using oClient As New TcpClient("localhost", iPort)
Using oStream As NetworkStream = oClient.GetStream()
aData = New Byte(255) {}
Console.WriteLine("Waiting...")
iBytes = oStream.Read(aData, 0, aData.Length)
sLogger = Encoding.ASCII.GetString(aData, 0, iBytes)
Console.WriteLine($"Logger: {sLogger}")
Using oPort = New SerialPort("COM3", 9600, Parity.None)
oPort.Open()
oPort.WriteLine(sLogger)
Do While sDevice = String.Empty
Threading.Thread.Sleep(1000)
sDevice = oPort.ReadExisting
Loop
Console.WriteLine($"Device: {sDevice}")
oPort.Close()
End Using
End Using
End Using
End Sub
我怎样才能可靠地清除输入缓冲区?我找到了几个讨论它的 SO 帖子,但是 none 已经能够解决我的具体问题。
现在可以使用了。
事实证明,应用程序在超时前发送了其中三个 ChrW(3)
'pings',而我的代码只接收了第一个。这使得它看起来好像输入缓冲区实际上没有被清除。这也是导致结果断断续续的原因。
我通过颠倒我的代码和虚拟串行端口之间的关系发现了这一点,使我的代码成为服务器而端口成为客户端。 (无论如何,这是一个更稳定的模型。)
这是更新后的代码:
Private Sub TcpListener()
Dim oIPAddress As IPAddress
Dim oListener As TcpListener
Dim oClient As Socket
Dim aData As Byte()
Dim _
iIndex,
iPort,
iSize As Integer
Console.WriteLine("Starting TCP listener...")
iPort = 5001
oIPAddress = IPAddress.Parse("127.0.0.1")
oListener = New TcpListener(oIPAddress, iPort)
oListener.Start()
While True
Console.WriteLine($"Server is listening on port: {iPort}")
Console.WriteLine("Waiting for a connection...")
oClient = oListener.AcceptSocket()
Console.WriteLine("Connection accepted.")
Console.WriteLine("Ready to receive data...")
aData = New Byte(99) {}
iSize = oClient.Receive(aData)
Console.WriteLine($"Data recieved @ {Now}: ")
For iIndex = 0 To iSize - 1
Console.Write(Convert.ToChar(aData(iIndex)))
Next
Console.WriteLine()
oClient.Close()
End While
oListener.Stop()
End Sub
我正在编写一个小型串行代理,以便我可以窃听遗留应用程序和它打算控制的设备之间的对话。
我的计划是:
- 使用将串行数据包发送到 TCP 端口的虚拟串行端口拦截应用程序的命令
- 将这些命令中继到设备
- 将设备的响应中继回应用程序。
到目前为止,当我只使用我的测试命令时它工作可靠。但是,当我使用该应用程序启动通信时,它会间歇性地失败。显然,该应用程序通过网络发送 'wake-up ping' 以验证与设备的连接是否成功。 'ping' 作为单字节值 ChrW(3)
出现,设备响应 =>
(成功)。只要输入缓冲区在我尝试读取之前是清空的,它就可以正常工作。
那是断断续续的部分。有时 ChrW(3)
会卡在那里,有时不会。随后的调用只是堆积在它之上。另一方面,我的测试命令总是清除。好像就是那个低阶角色的问题。
这是我的代码,我认为非常简单:
Private Sub TcpClient()
Dim aData As Byte()
Dim _
sLogger,
sDevice As String
Dim _
iBytes,
iPort As Integer
sDevice = String.Empty
iPort = 5001
Using oClient As New TcpClient("localhost", iPort)
Using oStream As NetworkStream = oClient.GetStream()
aData = New Byte(255) {}
Console.WriteLine("Waiting...")
iBytes = oStream.Read(aData, 0, aData.Length)
sLogger = Encoding.ASCII.GetString(aData, 0, iBytes)
Console.WriteLine($"Logger: {sLogger}")
Using oPort = New SerialPort("COM3", 9600, Parity.None)
oPort.Open()
oPort.WriteLine(sLogger)
Do While sDevice = String.Empty
Threading.Thread.Sleep(1000)
sDevice = oPort.ReadExisting
Loop
Console.WriteLine($"Device: {sDevice}")
oPort.Close()
End Using
End Using
End Using
End Sub
我怎样才能可靠地清除输入缓冲区?我找到了几个讨论它的 SO 帖子,但是 none 已经能够解决我的具体问题。
现在可以使用了。
事实证明,应用程序在超时前发送了其中三个 ChrW(3)
'pings',而我的代码只接收了第一个。这使得它看起来好像输入缓冲区实际上没有被清除。这也是导致结果断断续续的原因。
我通过颠倒我的代码和虚拟串行端口之间的关系发现了这一点,使我的代码成为服务器而端口成为客户端。 (无论如何,这是一个更稳定的模型。)
这是更新后的代码:
Private Sub TcpListener()
Dim oIPAddress As IPAddress
Dim oListener As TcpListener
Dim oClient As Socket
Dim aData As Byte()
Dim _
iIndex,
iPort,
iSize As Integer
Console.WriteLine("Starting TCP listener...")
iPort = 5001
oIPAddress = IPAddress.Parse("127.0.0.1")
oListener = New TcpListener(oIPAddress, iPort)
oListener.Start()
While True
Console.WriteLine($"Server is listening on port: {iPort}")
Console.WriteLine("Waiting for a connection...")
oClient = oListener.AcceptSocket()
Console.WriteLine("Connection accepted.")
Console.WriteLine("Ready to receive data...")
aData = New Byte(99) {}
iSize = oClient.Receive(aData)
Console.WriteLine($"Data recieved @ {Now}: ")
For iIndex = 0 To iSize - 1
Console.Write(Convert.ToChar(aData(iIndex)))
Next
Console.WriteLine()
oClient.Close()
End While
oListener.Stop()
End Sub