You should think of Serial Port connections as streaming data. Each time you receive data, you should expect that it can be a full message, only a partial message or several messages. It all depends on how fast the data arrives and how quickly you can read the application from the queue. Therefore, you are right in thinking that you need a buffer. However, what you may not yet realize is that there is no way to know, strictly through the serial port, where each message starts and ends. This must be processed according to an agreed protocol between the sender and the recipient. For example, many people use the standard start of text (STX) and end of text (ETX) characters to indicate the start and end of each message. That way, when you receive the data, you can find out when you received the full message.
For example, if you used the characters STX and ETX, you can make a class like this:
Public Class DataBuffer Private ReadOnly _startOfText As String = ASCII.GetChars(New Byte() {2}) Private ReadOnly _endOfText As String = ASCII.GetChars(New Byte() {4}) Public Event MessageReceived(ByVal message As String) Public Event DataIgnored(ByVal text As String) Private _buffer As StringBuilder = New StringBuilder Public Sub AppendText(ByVal text As String) _buffer.Append(text) While processBuffer(_buffer) End While End Sub Private Function processBuffer(ByVal buffer As StringBuilder) As Boolean Dim foundSomethingToProcess As Boolean = False Dim current As String = buffer.ToString() Dim stxPosition As Integer = current.IndexOf(_startOfText) Dim etxPosition As Integer = current.IndexOf(_endOfText) If (stxPosition >= 0) And (etxPosition >= 0) And (etxPosition > stxPosition) Then Dim messageText As String = current.Substring(0, etxPosition + 1) buffer.Remove(0, messageText.Length) If stxPosition > 0 Then RaiseEvent DataIgnored(messageText.Substring(0, stxPosition)) messageText = messageText.Substring(stxPosition) End If RaiseEvent MessageReceived(messageText) foundSomethingToProcess = True ElseIf (stxPosition = -1) And (current.Length <> 0) Then buffer.Remove(0, current.Length) RaiseEvent DataIgnored(current) foundSomethingToProcess = True End If Return foundSomethingToProcess End Function Public Sub Flush() If _buffer.Length <> 0 Then RaiseEvent DataIgnored(_buffer.ToString()) End If End Sub End Class
I should also mention that it is typical for communication protocols to have a checksum bike through which you can determine if a message has been damaged during transmission between the sender and the receiver.
source share