网络协议编码
Posted xuuold
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络协议编码相关的知识,希望对你有一定的参考价值。
网络协议,可以通过位来做标识符。
客户端(C#)封包拆包
1. 划分协议号
主要操作 1 ~ 16,占四位 0000
次要操作 1 ~ 16,占四位 0000
相乘 共 256 种操作
5 - 5 的话 通过位运算塞进一个 byte,即 01010101,int 即 85
2. 将 bit 数据封成 byte
2.1 使用 BitArray
2.2 int 与 BitArray 互转
BitArray 的存储是从低位向高位排列的,比如 85 ,二进制为 01010101
存在 BitArray 里就是 True False True False True False True False
public static int BitToInt(BitArray bit) int res = 0; for (int i = 0; i < bit.Count; i++) res = bit[i] ? res + (1 << i) : res; return res;
用例 1
byte[] a = 60 ; BitArray bit = new BitArray(a); print(a.Length); print(bit.Length); print(BitPack.BitToInt(bit));
打印
用例 2,也可以将 byte[] 拆包成 BitArray
byte[] a = 60, 255 ; BitArray bit = new BitArray(a); print(a.Length); print(bit.Length); print(BitPack.BitToInt(bit));
打印
可以发现,因为没有切分长度大于 8 的 BitArray,他把两个数并起来了,需要再处理。
注:最大储值 11111111 = 255
2.3 拆分 BitArray
public static List<int> SplitMixedInt(BitArray bit, int amount, List<int> length) //if (bit.Length > 8) // return null; List<int> final = new List<int>(); int lengthSum = 0; for (int i = 0; i < length.Count; i++) final.Add(BitToInt(bit, lengthSum, length[i])); lengthSum += length[i]; final.Reverse(); return final;
用例 4
byte[] mixedInt = 85 ; BitArray bit = new BitArray(mixedInt); int[] getInt = BitPack.SplitMixedInt(bit, 4, 4); print(getInt[0] + "," + getInt[1]); int newInt = BitPack.BitToInt(bit, 0, 4); print(newInt);
打印
下一步就要考虑,如何将 int 推入 BitArray 且只占用目标位数
2.4 将 int 以任意长度推进 BitArray
目前考虑的是从十进制转二进制字符串,再切分字符串给 BitArray 赋值。
C# 进制转换(二进制、十六进制、十进制互转) - 冰碟 - 博客园
int d = 10; //十进制转二进制字符串 Console.WriteLine(Convert.ToString(d,2)); //输出: 1010
public static BitArray Pack(BitArray bit, int number, int startPos, int length) if (bit == null) return null; if (bit.Length < startPos + length) return null; string bNumStr = Convert.ToString(number, 2); if(bNumStr.Length > length) return null; for (int i = 0; i < length; i++) int idx = bNumStr.Length - 1 - i; if(idx < 0) bit.Set(startPos + i, false); else bit.Set(startPos + i, bNumStr[idx] == ‘1‘ ? true : false); return bit;
用例 5
BitArray bit = new BitArray(8); BitPack.Pack(bit, 2, 0, 3); BitPack.Pack(bit, 13, 3, 5); foreach(bool b in bit) print(b);
打印
2.5 将 BitArray 转换成 Byte[]
Convert a BitArray to byte[] in C#
public static byte[] ToByteArray(BitArray bits) if (bits == null) return null; int numBytes = bits.Count / 8; if (bits.Count % 8 != 0) numBytes++; byte[] bytes = new byte[numBytes]; int byteIndex = 0, bitIndex = 0; for (int i = 0; i < bits.Count; i++) if (bits[i]) bytes[byteIndex] |= (byte)(1 << (7 - bitIndex)); bitIndex++; if (bitIndex == 8) bitIndex = 0; byteIndex++; return bytes;
用例 6
BitArray bit = new BitArray(8); BitPack.Pack(bit, 2, 0, 3); BitPack.Pack(bit, 13, 3, 5); byte[] byteArray = BitPack.ToByteArray(bit); print(byteArray.Length); foreach (object obj in byteArray) print(obj.ToString());
打印
3. 服务器(Python3)封包拆包
由于 C# 中的 BitArray 是左起为低位,所以跟 Python 解出来的是不一样的结果。
BitArray bit = new BitArray(8); BitPack.Pack(bit, 2, 0, 4); BitPack.Pack(bit, 13, 4, 4); byte[] byteArray = BitPack.ToByteArray(bit); print(BitPack.BitToInt(bit, 0, 4)); print(BitPack.BitToInt(bit, 4, 4)); string s = ""; foreach (bool b in bit) s += b + " "; print(s); print(BitPack.BitToInt(bit, 0, 8));
服务端这边,则默认是右边为低位,其实影响不大
def ByteToBit(bytes): bits = [] for i in bytes: bits.append(i) return bits
print(‘收到:‘, datar) print(‘转码bit:‘, ByteToBit(data))
3.1 将 byte[] 转换成位数组
def ByteToBits(self, bytes): bits = [] for byte in bytes: n0 = 1 if (byte & 0x01) == 0x01 else 0; n1 = 1 if (byte & 0x02) == 0x02 else 0; n2 = 1 if (byte & 0x04) == 0x04 else 0; n3 = 1 if (byte & 0x08) == 0x08 else 0; n4 = 1 if (byte & 0x10) == 0x10 else 0; n5 = 1 if (byte & 0x20) == 0x20 else 0; n6 = 1 if (byte & 0x40) == 0x40 else 0; n7 = 1 if (byte & 0x80) == 0x80 else 0; bits.append(n7); bits.append(n6); bits.append(n5); bits.append(n4); bits.append(n3); bits.append(n2); bits.append(n1); bits.append(n0); return bits
用例 7
// 客户端封包 BitArray bit = new BitArray(12); BitPack.Pack(bit, 2, 0, 4); BitPack.Pack(bit, 13, 4, 4); BitPack.Pack(bit, 13, 8, 4); byte[] byteArray = BitPack.ToByteArray(bit); print(BitPack.BitToInt(bit, 0, 4)); print(BitPack.BitToInt(bit, 4, 4)); string s = ""; foreach (bool b in bit) s += b + " "; print(s); print(BitPack.BitToInt(bit, 0, 8));
以上是关于网络协议编码的主要内容,如果未能解决你的问题,请参考以下文章