网络协议编码

网络协议,可以通过位来做标识符。

客户端(C#)封包拆包

1. 划分协议号

主要操作 1 ~ 16,占四位 0000

次要操作 1 ~ 16,占四位 0000

相乘 共 256 种操作

5 - 5 的话 通过位运算塞进一个 byte,即 01010101,int 即 85

2. 将 bit 数据封成 byte

2.1 使用 BitArray 

C# 点阵列(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));

 

猜你喜欢

转载自www.cnblogs.com/xuuold/p/11257471.html