在硬件的文檔,使我們能夠通過UDP/IP控制它, 我發現下面的片段:C#小端或大端?
在該通信協議,DWORD是一個4個字節的數據,WORD是一個2個字節的數據, BYTE是一個單字節數據。存儲格式爲小端,即4個字節(32位)的數據存儲爲:d7-d0,d15-d8,d23-d16,d31-d24;雙字節(16位)數據存儲爲:d7-d0,d15-d8。
我想知道這是如何轉換爲C#? 在發送之前是否需要轉換內容? 例如,如果我想發送一個32位整數或4個字符的字符串?
在硬件的文檔,使我們能夠通過UDP/IP控制它, 我發現下面的片段:C#小端或大端?
在該通信協議,DWORD是一個4個字節的數據,WORD是一個2個字節的數據, BYTE是一個單字節數據。存儲格式爲小端,即4個字節(32位)的數據存儲爲:d7-d0,d15-d8,d23-d16,d31-d24;雙字節(16位)數據存儲爲:d7-d0,d15-d8。
我想知道這是如何轉換爲C#? 在發送之前是否需要轉換內容? 例如,如果我想發送一個32位整數或4個字符的字符串?
C#本身沒有定義字節順序。但是,無論何時轉換爲字節,您都在做出選擇。 BitConverter類有一個IsLittleEndian字段告訴你它將如何表現,但它沒有給出選擇。 BinaryReader/BinaryWriter也是如此。我的MiscUtil庫有一個EndianBitConverter類,它允許你定義字節序; BinaryReader/Writer有類似的等價物。沒有在線使用指南恐怕,但他們很平凡:)
(EndianBitConverter也有一塊功能,這是不存在於正常的BitConverter,這是在一個字節數組就地轉換)
Re little-endian,簡短的回答(我需要做什麼)是「可能不是,但它取決於你的硬件」。你可以檢查:
bool le = BitConverter.IsLittleEndian;
根據這說的,你可能想扭轉部分緩衝區。或者,喬恩Skeet具有特定的endian轉換器here(尋找EndianBitConverter)。
請注意,itanium(例如)是big-endian。大多數英特爾都是小端。
重新具體的UDP/IP ...?
您需要了解網絡字節順序以及CPU端位置。
通常對於TCP/UDP通信,您總是使用htons
函數(和ntohs
及其相關函數)將數據轉換爲網絡字節順序。
通常網絡順序是big-endian,但在這種情況下(出於某種原因!)通信是小端,所以這些功能不是很有用。這很重要,因爲您不能假定他們實施的UDP通信遵循任何其他標準,但如果您擁有大端架構,則您也會生活困難,因爲您無法用htons
包裝所有內容,因爲您應該:-(
但是,如果你從一個英特爾x86架構的到來,那麼你已經小尾數,因此只要發送數據,而無需轉換。
您還可以使用
IPAddress.NetworkToHostOrder(...)
對於短,INT或長。
如果你分析和性能並不重要,考慮這個非常簡單的代碼:
private static byte[] NetworkToHostOrder (byte[] array, int offset, int length)
{
return array.Skip (offset).Take (length).Reverse().ToArray();
}
int foo = BitConverter.ToInt64 (NetworkToHostOrder (queue, 14, 8), 0);
我與打包擺弄數據的UDP組播和我需要的東西來重新排序UINT16個字節,因爲我注意到在分組報頭(Wireshark的)的錯誤,所以我提出這樣的:
private UInt16 swapOctetsUInt16(UInt16 toSwap)
{
Int32 tmp = 0;
tmp = toSwap >> 8;
tmp = tmp | ((toSwap & 0xff) << 8);
return (UInt16) tmp;
}
在UInt32的的情況下,
private UInt32 swapOctetsUInt32(UInt32 toSwap)
{
UInt32 tmp = 0;
tmp = toSwap >> 24;
tmp = tmp | ((toSwap & 0xff0000) >> 8);
tmp = tmp | ((toSwap & 0xff00) << 8);
tmp = tmp | ((toSwap & 0xff) << 24);
return tmp;
}
這僅僅是測試
private void testSwap() {
UInt16 tmp1 = 0x0a0b;
UInt32 tmp2 = 0x0a0b0c0d;
SoapHexBinary shb1 = new SoapHexBinary(BitConverter.GetBytes(tmp1));
SoapHexBinary shb2 = new SoapHexBinary(BitConverter.GetBytes(swapOctetsUInt16(tmp1)));
Debug.WriteLine("{0}", shb1.ToString());
Debug.WriteLine("{0}", shb2.ToString());
SoapHexBinary shb3 = new SoapHexBinary(BitConverter.GetBytes(tmp2));
SoapHexBinary shb4 = new SoapHexBinary(BitConverter.GetBytes(swapOctetsUInt32(tmp2)));
Debug.WriteLine("{0}", shb3.ToString());
Debug.WriteLine("{0}", shb4.ToString());
}
從中輸出是這樣的:
0B0A: {0}
0A0B: {0}
0D0C0B0A: {0}
0A0B0C0D: {0}
...是使用安騰.NET的人? – SingleNegationElimination 2009-03-26 23:09:44
hmm。我剛剛做的基礎研究似乎表明,Windows始終是小端(安騰可以支持任何字節序)。因此,BitConverter.IsLittleEndian看起來像*總是*會返回true,除非您在itanium上的big-endian linux上運行像Mono這樣的Wierld。 請參閱http://blogs.msdn.com/larryosterman/archive/2005/06/07/426334.aspx – piers7 2010-01-05 07:55:01