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:
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.
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