http://www.dotblogs.com.tw/billchung/archive/2012/02/05/67809.aspx
情境二:具備開頭結尾字元
有一些通訊協的形式是具備了開頭結尾字元形式的,當然不一定是一個字,不過通常的情形是開頭或結尾字元絕不會出現在中間的資料內容段中,以下的圖例是以大寫字母S做為開頭字元;而大寫E字母做為結尾字元的通訊協定形式。
純接收的狀況:
這其實會有幾種不同的適用方式,如果是純接收的狀態以 [Serial Port 系列(11) 基本篇 -- 利用執行緒讀取資料] 的範例來接收的話,我們有可能會這樣收到資料:
第一次:S9987
第二次:4366ES02
第三次:75543298E
首先在方法內宣告一個 List(Of Byte) / List<Byte> 型別的變數 tempList,將每次讀到的值先指派給receiveValue 再存放在這個變數所指向的執行個體;
在存放進 tempList 前我們必須先該 receivedValue 值的判斷以便處理不同的情況。當讀到的值與大寫S (也就是開頭字元) 的 Byte 值相同時則先清除 tempList 的內容
(這表示在S之前的資料都不要了) 再將 S 的值加入 tempList;當讀到的值與大寫E (也就是結尾字元) 的 Byte 值相同時則先加入 E 的值到 tempList 然後呼叫自訂的 parse 方法處理;
若是讀到 –1 則不管它,若是讀到並非以上的值時則直接加入到 tempList (這有一個假設是讀到的值都是可以轉成可見字元的,實際上為安全起見應該要再加上此一判斷才對)。
由於C# 的 switch case 無法像 Viusal Basic 這樣瞎弄,所以在 C# 的程式碼中我多宣告了兩個類別內的全域常數。
const
Int32 S = 83;
const
Int32 E = 69;
private
void
DoReceive()
{
List<Byte> tempList = new
List<Byte>();
while
(receiving)
{
Int32 receivedValue = comport.ReadByte();
switch
(receivedValue)
{
case
S:
tempList.Clear();
tempList.Add((Byte)receivedValue);
break;
case
E:
tempList.Add((Byte)receivedValue);
parse(tempList);
break;
case
-1:
break;
default:
tempList.Add((Byte)receivedValue);
break;
}
}
}
private
void
parse(List<Byte> tempList)
{
MessageBox.Show(tempList[0].ToString());
if
(tempList[0] == (Byte)S && tempList[tempList.Count - 1] == (Byte)E)
{
tempList.RemoveAt(0);
tempList.RemoveAt(tempList.Count - 1);
Display d = new
Display(DisplayText);
this.Invoke(d, new
Object[] { tempList.ToArray() });
}
}
private
void
DisplayText(Byte[] buffer)
{
TextBox1.Text += String.Format("{0}{1}", Encoding.ASCII.GetString(buffer), Environment.NewLine);
totalLength = totalLength + buffer.Length;
Label2.Text = totalLength.ToString();
}
http://www.dotblogs.com.tw/billchung/archive/2012/02/18/69599.aspx
情境三:具備長度資料
有些協定是會帶長度資料的,以下的例子在第一個Byte 所帶的開頭碼為十進位值 249 ,第二個Byte 所代表的是後面資料內容的長度。
Part 3
private
void
DoReceive()
{
List<Byte> tempList = new
List<Byte>();
Byte[] buffer = new
Byte[1024];
Int32 messageDataLength = 0;
while
(receiving)
{
Thread.Sleep(100);
if
(comport.BytesToRead > 0)
{
Int32 receivedLength = comport.Read(buffer, 0, buffer.Length);
Array.Resize(ref
buffer, receivedLength);
tempList.AddRange(buffer);
Array.Resize(ref
buffer, 1024);
}
if
(tempList.Count > 0)
{
if
(messageDataLength == 0)
{
messageDataLength = GetMessageDataLength(tempList);
}
else
{
messageDataLength = Parse(tempList, messageDataLength);
}
}
}
}
private
Int32 GetMessageDataLength(List<Byte> tempList)
{
if
(tempList.Count >= 2)
{
Int32 startIndex = tempList.IndexOf(head);
if
(startIndex >= 0 && startIndex < tempList.Count )
{
return
Convert.ToInt32(tempList[startIndex + 1]);
}
else
{ return
0; }
}
else
{ return
0; }
}
private Int32 Parse(List<Byte> tempList, Int32 messageDataLength)
{
if
(tempList.Count >= messageDataLength)
{
Byte[] tempArray = new
Byte[messageDataLength];
Int32 startIndex = tempList.IndexOf(head);
if
(startIndex >= 0)
{
tempList.CopyTo(startIndex + 2, tempArray, 0, messageDataLength);
tempList.RemoveRange(0, startIndex + messageDataLength + 2);
messageDataLength = GetMessageDataLength(tempList);
Display d = new
Display(DisplayText);
this.Invoke(d, new
Object[] { tempArray });
}
}
return
messageDataLength;
}