输入缓冲区在读取后不能可靠地清除

The input buffer does not reliably clear after reading

我正在编写一个小型串行代理,以便我可以窃听遗留应用程序和它打算控制的设备之间的对话。

我的计划是:

  1. 使用将串行数据包发送到 TCP 端口的虚拟串行端口拦截应用程序的命令
  2. 将这些命令中继到设备
  3. 将设备的响应中继回应用程序。

到目前为止,当我只使用我的测试命令时它工作可靠。但是,当我使用该应用程序启动通信时,它会间歇性地失败。显然,该应用程序通过网络发送 '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