Search code examples
tcpclient

The input buffer does not reliably clear after reading


I'm writing a small serial proxy so that I can eavesdrop on the conversation between a legacy application and the device it's intended to control.

My plan is to:

  1. Intercept the application's commands using a Virtual Serial Port that sends Serial packets to a TCP port
  2. Relay those commands to the device
  3. Relay the device's responses back to the application.

It's working reliably so far when I use only my test commands. However, it's failing intermittently when I initiate communications using the application. Apparently the app sends a 'wake-up ping' over the wire to verify a successful connection to the device. That 'ping' comes as a single byte value of ChrW(3), to which the device responds => (success). This works well as long as the input buffer is clear before I attempt to read it.

That's the intermittent part. Sometimes that ChrW(3) gets stuck in there, sometimes it doesn't. Subsequent calls just pile on top of it. On the other hand, my test commands always clear out. It just seems to be something about that low-order character.

Here's my code, pretty simple I'd think:

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

How can I reliably clear that input buffer? I've found several SO posts discussing it, but none have been able to solve my specific problem.


Solution

  • It's working now.

    It turns out that the application sends three of these ChrW(3) 'pings' before timing out, where my code was picking up only the first one. This was making it seem as though the input buffer wasn't being cleared when it actually was. It was also the cause of the intermittent results.

    I discovered this by reversing the relationship between my code and the Virtual Serial Port, making my code the server and the port the client. (This is a more stable model anyway.)

    Here's the updated code:

    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