这个问题在某种程度上延伸了我之前提出的问题c# using marshalling for packet parsing。 我必须解析一个可变大小的数据包,虽然标题大小是固定的,但其中的数据包可以是不同的大小,并且可能在同一个数据包中存在多于一种类型。
例如,数据包的标题中包含以下字段:
1) username(12 bytes)
2 password(12 bytes)
3) id_number(4 bytes)
4) may be 1 or combination of other data packets of variable size(size can be 12, 16 or 512 bytes)
5) crc(2 bytes)
现在数据包可以跟随
a) data packet type 1
1) size(2 bytes)
2) name(12 bytes)
3) id_number(2 bytes)
b) data packet type 2
1) size(2 bytes)
2) data(24 bytes)
3) id_number(1 byte).
因此可以有type1或type2。两种类型也可能存在。我的问题是如何使用编组来解析这些数据包,或者任何人都可以建议其他方式。 我想补充的另一件事是数据包的第1和第3字段将始终分别是数据包大小(2字节)和数据包ID号(1字节)。数据包的第二个字段可以是任何大小可变的(2,3,13,18,515)。
答案 0 :(得分:1)
作为替代方案,您可以使用LINQ(假设正在使用ASCII编码):
var packet = new byte[]{
97, 108, 101, 120, 0, 0, 0, 0, 0, 0, 0, 0, // username
112, 97, 115, 115, 119, 111, 114, 100, 0, 0, 0, 0, //password
49, 50, 51, 0, // id_number
0, 53, 0, 0, 1, // 1st data packet
0, 54, 1, 2, 5, 2, // 2nd data packet
49, 0 // crc
};
var username = Encoding.ASCII.GetString(packet.Take(12).ToArray());
var password = Encoding.ASCII.GetString(packet.Skip(12).Take(12).ToArray());
var idNumber = Encoding.ASCII.GetString(packet.Skip(24).Take(4).ToArray());
var data = packet.Skip(28).Take(packet.Length - 30).ToArray();
var crc = Encoding.ASCII.GetString(packet.Skip(packet.Length - 2).ToArray());
var nextDataPackedPos = 0;
var nextDataPackedPos = 0;
var dataPackets = data
.TakeWhile(b => nextDataPackedPos < data.Length)
.Zip(data.Skip(nextDataPackedPos), (a, b) =>
{
var size = Int32.Parse(
Encoding.ASCII
.GetString(data.Skip(nextDataPackedPos).Take(2).ToArray())
.Trim('\0')
);
var result = data.Skip(nextDataPackedPos).Take(size).ToArray();
nextDataPackedPos += size;
return result;
}).ToList();
代码首先将数据部分与数据包字节分开。然后它读取每个数据包的大小,并根据它创建一个包含数据包字节的等大小数组。它会前进到下一个数据包的开头,直到到达数组的末尾。