[C#.NET] 處理通訊協定的事前準備

  • 30778
  • 0
  • C#
  • 2016-07-11

[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 整除
    image_thumb1_thumb

    法一:使用 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 來轉型
    image_thumb8_thumb
    image_thumb6_thumb 
    
    var hex = BitConverter.GetBytes(dec);

  • Result:byte[]{52,18}
           
    PS.若沒有選擇正確的型別,預設是會用 32 bit 來轉換,像下圖直接轉 1234,就多了 2 個byte。      
    image_thumb2_thumb 

Big Endian 和 Little Endian眼尖的人應該不難發現上面的例子,轉換的結果不一樣,使用 Convert.ToByte 方法的結果如下圖:

image_thumb13_thumb

 

字串由左至右閱讀,轉換後,陣列索引值越低,存放高位元組,這稱為 Big Endian,使用 BitConverter.GetBytes 方法的結果如下圖:

image_thumb14_thumb

字串由左至右閱讀,轉換後,陣列索引值越低,存放低位元組,這稱為 Little Endian
若還是不懂的話,咱們再看個例子0x12345678

image_thumb15_thumb

這只是排列分佈順序顛倒而已,就看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.若選擇錯的資料型態會拋出例外,意思是說陣列數不足;也有可能丟失資料。

image_thumb16_thumb

 

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo