from http://hi.baidu.com/qianko/blog/item/7ffe0701eb0c0fc7267fb518.html
最近在寫一個簡訊下發功能,用戶端使用c#和java的簡訊網關的進行網路通訊。
之前使用java進行開發,一切正常,改用c#無法收到網關應答。
想了半天意識到是不是網路位元組序問題,
java預設就是大端位元組序,和網路位元組序是一至的,所以不轉換也不會有問題,
而c#在windows平台上是小端位元組序。
網路發送位元組流是按大端序發送,也就是從左至右發送,和c#的小端序相反,造成網關不能正常識別協議。
嘗試c#中轉換一下位元組序,通訊成功。
c#中位元組序轉換有兩種方法。
非字串使用 System.BitConverter.GetBytes()方法,先讀入位元組數組中,然後再用Array.Reverse()對byte數組反序一下,得到大端序位元組數組。
代碼:
short x = 6;
byte[] a=System.BitConverter.GetBytes(x); //得到小端位元組序數組
Array.Reverse(a); //反轉數組轉成大端。
另外c#直接提供了網路位元組序轉換方法。
System.Net.IPAddress.HostToNetworkOrder(本機到網路轉換)
System.Net.IPAddress.NetworkToHostOrder(網路位元組轉成本機)
推薦使用這種方法,簡單有效。
程式碼範例:
short x = 6;
short b = System.Net.IPAddress.HostToNetworkOrder(x); //把x轉成相應的大端位元組數
byte[] bb = System.BitConverter.GetBytes(b);//這樣直接取到的就是大端位元組序位元組數組。
對於字串型:使用 System.Text.Encoding.Default.GetBytes();直接取字串對應位元組數組。
不知道為什麼這個方法取到的直接就是大端位元組數組。不用轉換。
後來查了一下,關於字串的位元組序問題,因為gbk和utf-8都是以單個位元組表示數位,所以不存在位元組序問題,在多個不同系統架構都用。對於utf-16,則是以雙位元組表示一個整數,所以為會有位元組序問題,分大小端unicode。
System.Text.Encoding.Default.GetBytes();在我的簡體中文系統上是以gb2312的編碼,也就是單個字來進行編碼的,所以也不會有位元組序問題。
補充:“對於任何字元編碼,編碼單元的順序是由編碼方案指定的,與endian無關。例如GBK的編碼單元是位元組,用兩個位元組表示一個漢字。這兩個位元組的順序是固定的,不受CPU位元組序的影響。UTF-16的編碼單元是word(雙位元組),word之間的順序是編碼方案指定的,word內部的位元組排列才會受到endian的影響。”,所以utf-8也沒有位元組序的問題。位元組序問題之存在於需要使用兩個位元組以上來表示整數。而UTF-8隻是一串位元組流,不存在位元組序問題,不過將這些位元組流翻譯成Unicode比其他的傳輸方式複雜。以位元組為單位編碼的,無論一個漢字是多少個位元組,都無位元組序問題。
你注意,位元組序問題不是指多個位元組傳輸的先後,這個是固定的無異議的。而是指一個多位元組編碼在機器中的表示方式問題。
char str[] = "abaksdkakskasklasflk";這個無位元組序問題。
但
int str[] = {0x11223344, 2, 3 }就有位元組序問題了。因為str[0]同樣數值不同機器中表示不同。
而剩下的, 就是字元編碼內部的位元組序了。比如UTF-16是用兩個位元組表示一個字元,但是這兩個位元組內部如何排序,系統並不知道,所以必須指定位元組序。但是UTF-8由於幾個位元組表示並不相同,一定要從那個表示長度的位元組開始讀,相當於一開始就知道該從哪裡是隊頭隊尾,所以不存在位元組序問題。