C# 编组可变大小的数据包

C# 编组可变大小的数据包,c#,marshalling,C#,Marshalling,这个问题在某种程度上是我先前提出的问题的延伸。 我必须解析一个可变大小的数据包,尽管报头大小是固定的,但它里面的数据包可以是不同大小的,并且可能有不止一种类型存在于同一个数据包中 例如,数据包的报头中有以下字段: 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

这个问题在某种程度上是我先前提出的问题的延伸。 我必须解析一个可变大小的数据包,尽管报头大小是固定的,但它里面的数据包可以是不同大小的,并且可能有不止一种类型存在于同一个数据包中

例如,数据包的报头中有以下字段:

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。这两种类型也可能同时存在。我的问题是如何使用编组来解析这些数据包,或者任何人都可以提出其他方法。
我还想补充一点,数据包的第一个和第三个字段将始终分别是数据包大小(2字节)和数据包id号(1字节)。数据包的第二个字段可以是任何大小可变的内容(2、3、13、18、515)

作为替代方案,您可以使用LINQ(假设正在使用ASCII编码):

var数据包=新字节[]{
97108101120,0,0,0,0,0,0,0,0,//用户名
112、97、115、115、119、111、114、100、0、0、0、//密码
49,50,51,0,//id\u编号
0,53,0,0,1,//第一个数据包
0、54、1、2、5、2、//第二个数据包
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数据包=数据
.TakeWhile(b=>nextDataPackedPos
{
var size=Int32.Parse(
Encoding.ASCII
.GetString(data.Skip(nextDataPackedPos).Take(2.ToArray())
.Trim(“\0”)
);
var result=data.Skip(nextDataPackedPos).Take(size.ToArray();
nextDataPackedPos+=大小;
返回结果;
}).ToList();

代码首先将数据段与数据包字节分开。然后读取每个数据包的大小,并在此基础上创建一个大小相等的数组,其中包含数据包的字节。它会一直前进到下一个数据包的开头,直到到达数组的结尾。

大小可以是12、16或512字节2个问题:1。大小为12的数据包的结构是什么?2.12、16和512是唯一可能的大小,或者可能有介于16和512之间的值?数据包大小可以是5、6、16、21、518。那么,报头中的字段#4是一个2字节的短整数吗?4字节整数?您必须使用BinaryReader来转换数据包。没什么大不了的。字段4是一个接一个的数据包。因此,它们可能有1、2、3、…50个或更多的数据包。因此,字段4的总大小是可变的。谢谢Alex,您的解决方案看起来是正确的。让我试试我的代码。
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();