[C#.NET] 處理通訊協定的事前準備
開始處理之前,我們要先瞭解一些東西
單位
計算機概論應該都有學到
- 1 bit : 位元只有 0 or 1 ,對岸翻成比特
- 1 byte = 8 bit
- 1 word = 2 bytes = 16 bits
文字格式
通常有兩種格式,要看 Server 吃什麼格式。
- ASCII:
在文件的表示,比如:1234 - Hexadecimal:
在文件的表示法裡會用 0x 開頭,比如:0x1234
處理文字格式對應的類別,字串轉陣列
不論是Socket or Serial都是要餵byte[]格式,所以學會轉byte[]是寫程式需要處理的第一步
- ASCII:
會用到 Encoding.GetBytes Method (String)方法
var ascii = Encoding.ASCII.GetBytes("1234");
它會把 "1234" 轉成4 個byte ,
Result:byte[]{49,50,51,52}。 - Hexadecimal:
範例:0x1234 轉成 byte[]
這時候我們必須要把Hex格式的資料,兩兩一組當成一個 byte,一定要被 2 整除
法一:使用 Convert.ToByte 方法 :return Enumerable.Range(0, hex.Length) .Where(x => x % 2 == 0) .Select(x => Convert.ToByte(hex.Substring(x, 2), 16)) .ToArray(); }
Result:byte[]{18,52}
參考來源:http://stackoverflow.com/questions/321370/convert-hex-string-to-byte-array
法二:使用 BitConverter.GetBytes 方法:
我們可以發現到它的多載都是整數,所以我們需要兩個步驟:
Step1. 把字串轉成10進制的整數。
Step2. 調用BitConverter.GetBytes 方法。
選對型別轉換很重要,1 個 byte 代表 255,2 個 byte 代表 255*255 = 65535,也就是 16 個bit
2 byte = 16 bit ,所以我們可以選ushort/UInt 來轉型
var hex = BitConverter.GetBytes(dec);
- Result:byte[]{52,18}
PS.若沒有選擇正確的型別,預設是會用 32 bit 來轉換,像下圖直接轉 1234,就多了 2 個byte。
Big Endian 和 Little Endian眼尖的人應該不難發現上面的例子,轉換的結果不一樣,使用 Convert.ToByte 方法的結果如下圖:
字串由左至右閱讀,轉換後,陣列索引值越低,存放高位元組,這稱為 Big Endian,使用 BitConverter.GetBytes 方法的結果如下圖:
字串由左至右閱讀,轉換後,陣列索引值越低,存放低位元組,這稱為 Little Endian
若還是不懂的話,咱們再看個例子0x12345678
這只是排列分佈順序顛倒而已,就看Server吃什麼樣的順序,我們可以透過 Array.Reverse 方法來顛倒陣列的順序,不過大多數我遇到的都是Big Endian
Array.Reverse(hex);
處理文字格式對應的類別,陣列轉 16 進制字串
當資料處理完之後,若需要檢視正確性,可能需要轉回 16 進制字串
- ASCII:
使用Encoding.GetString 方法 (Byte[]) - Hexadecimal:
法一:利用Byte.ToString(“X”)處理:{ StringBuilder sb = new StringBuilder(); foreach (var b in hexArray) { sb.Append(b.ToString("X").PadLeft(2, '0')); //sb.AppendFormat("{0:x2}", b); } return sb.ToString(); }
法二:利用 BitConverter.ToString 方法 (Byte[]) :
處理文字格式對應的類別,陣列轉 2 進制字串:
{ StringBuilder sb = new StringBuilder(); foreach (var b in HexArray) { sb.Append(Convert.ToString(b, 2).PadLeft(8, '0')); } return sb.ToString(); }
處理文字格式對應的類別,陣列轉 10 進制字串:
在使用 BitConverter 轉回整數時要注意選擇對的型態,這就跟上面提到轉Byte[]的方式一模一樣。
{ return BitConverter.ToUInt16(HexArray, 0).ToString(); }
PS.由於 BitConverter.ToInt 系列是使用 Little Endian,所以要反轉陣列,調用 Array.Reverse(HexArray)就可以了。
PS.不過BitConverter.ToString似乎是Big Endian,不需要反轉就能得到正確的結果。
PS.若選擇錯的資料型態會拋出例外,意思是說陣列數不足;也有可能丟失資料。
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET