使用C#來模擬python pack和unpack函數的效果的需求來自一次作業,作業做一個聯網的射擊游戲,那么不可避免地要進行服務端和客戶端地交互,但是服務端代碼由Python編寫,而客戶端代碼由C#完成,並且服務端發送數據又經過pack打包,這樣一來,客戶端就需要去解析收到的數據,然而沒有對應的庫或者函數可以用(又或者我沒有找到),所以我根據我的使用場景來實現了打包和解包的函數。本來不打算發出來,因為沒有經過嚴格的測試(又或者說只適用於我這里的問題),但如果你也有類似的問題,不妨看一看,可能會有啟發。
我的使用場景:
服務端向客戶端發送數據時,使用包頭+data的方式來避免粘包。首先把計算數據和包頭長度,而后將其pack成字符串,與data組合一並發送至客戶端,由客戶端進行解析。
pack format:4 bytes little endian (x86) by default
我觀察打印的的結果后,實現了c#端的對應打包解包函數如下:
C# - pack (pack之后是一個16進制串,需要把一個整數轉換成一個4字節小端,即低位存儲在低字節的16進制字符串)
1 /// <summary> 2 /// format the dec integer to a hex stream, for sending msg 3 /// </summary> 4 /// <param name="size"> dec integer </param> 5 /// <returns> hex stream </returns> 6 public string Dec2HexStream(int size) 7 { 8 9 string raw = "00000000"; 10 string hex = Convert.ToString(size, 16); 11 //Console.WriteLine("轉換字符串 " + hex + " 長度 " + hex.Length); 12 int hexLen = hex.Length; 13 if (hexLen > 8) 14 return "\x00\x00\x00\x00"; 15 else 16 { 17 // 100 -> 00 01 00 00 -> 00 00 01 00 18 hex = raw.Substring(0, 8 - hexLen) + hex; 19 } 20 //Console.WriteLine("加0字符串 " + hex); 21 22 string res = ""; 23 for (int i = 3; i >= 0; i--) 24 { 25 res += hex.Substring(i * 2, 2); 26 } 27 hex = res; 28 29 //Console.WriteLine("反轉字符串 " + hex); 30 res = ""; 31 for (int i = 0; i < 4; i++) 32 { 33 res += "\\x" + hex.Substring(i * 2, 2); 34 } 35 //Console.WriteLine("結果字符串 " + res); 36 return Regex.Unescape(res); 37 }
C# - unpack (對應的將4字節小端存儲的16進制字符串轉換成為一個整數)
1 /// <summary> 2 /// for recving msg and parsering the size of data 3 /// </summary> 4 /// <param name="s"> hex stream </param> 5 /// <returns>dec integer</returns> 6 public int HexStream2Dec(string s) 7 { 8 // 00 01 00 00 9 // 00 00 01 00 10 // \x01\x00\x00\x00 小端 11 UInt32 res = 0; 12 //Console.WriteLine("處理字符串 " + s); 13 string tmp = ""; 14 for (int i = 3; i >= 0; i--) 15 { 16 UInt32 m = Convert.ToUInt32(s[i]); 17 string hexs = Convert.ToString(m, 16); 18 tmp += hexs; 19 } 20 //Console.WriteLine("還原字符串 " + tmp + " 長度 " + (tmp.Length).ToString()); 21 res = Convert.ToUInt32(tmp, 16); 22 return (int)res; 23 }
本文首發、修改於 博客園 yocichen