c#使用编组进行数据包解析

本文关键字:数据包 | 更新日期: 2023-09-27 18:27:47

例如,我必须解析存储在ascii代码中byte[]中的数据包byte[]user=新byte[]{11211497116121117115104,0,0,0,0,49,51,51,0}其中前12个字节是服务器名,后4个字节是某个id。

通过浏览以前的stackoverflow帖子,我想出了这个代码

[StructLayout(LayoutKind.Explicit)]
struct packetrf
{
  public ulong servername
    {
        get
        {
            return (ulong)servername1 | ((ulong)servername2 << 8) | ((ulong)servername3 << 16) | ((ulong)servername4 << 24) | ((ulong)servername5 << 32) | ((ulong)servername6 << 40) | ((ulong)servername7 << 48) | ((ulong)servername8 << 56) | ((ulong)servername9 << 64) | ((ulong)servername10 << 72) | ((ulong)servername11 << 80) | ((ulong)servername12 << 88);
        }
    }
    [FieldOffset(0)]
    public byte servername1;
    [FieldOffset(1)]
    public byte servername2;
    [FieldOffset(2)]
    public byte servername3;
    [FieldOffset(3)]
    public byte servername4;
    [FieldOffset(4)]
    public byte servername5;
    [FieldOffset(5)]
    public byte servername6;
    [FieldOffset(6)]
    public byte servername7;
    [FieldOffset(7)]
    public byte servername8;
    [FieldOffset(8)]
    public byte servername9;
    [FieldOffset(9)]
    public byte servername10;
    [FieldOffset(10)]
    public byte servername11;
    [FieldOffset(11)]
    public byte servername12;
   [FieldOffset(12)]
    public Int32 imei_msn;
};
static private pack fromByte(byte[] arr)
{
    pack str = new pack();
    GCHandle handle = GCHandle.Alloc(arr, GCHandleType.Pinned);
    str = (pack)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(pack));
    handle.Free();
    return str;
}
static private void data_parser(byte[] pkt, int size, int indexno)
{
       packetrf data = fromByte(pkt);
        Console.WriteLine();
        Console.WriteLine(data.servername);
        Console.WriteLine(data.imei_msn);
        Console.ReadKey();
    }

public static void Main()
{
    byte[] user = new byte[] {112, 114, 97, 116, 121, 117, 115, 104, 0, 0, 0, 0, 49, 50, 51, 0}
    data_parser(user, 1, 2);
}

当我运行此代码时,servername的输出为7526488566770266736,imei_msn的输出为13106,它可能是ascii->hex->decimal格式。现在我面临的问题是,如何将这些数字转换为一些有意义的完整信息,如第一个数字转换为显示名称的字符串,第二个数字转换成十进制格式的imei_msn?

c#使用编组进行数据包解析

尝试使用固定大小的数组(请阅读此处https://stackoverflow.com/a/14629106/613130)

[StructLayout(LayoutKind.Explicit)]
struct packetrf
{
    [FieldOffset(0), MarshalAs(UnmanagedType.ByValArray, SizeConst=12)]
    public byte[] servername;
    [FieldOffset(12)]
    public Int32 imei_msn;
};

然后:

string serv = Encoding.ASCII.GetString(yourObject.servername).TrimEnd(''0');

或直接作为属性

public string serverName2
{
    get
    {
        return Encoding.ASCII.GetString(servername).TrimEnd(''0');
    }
}

记住TrimEnd,所有的''0'都将存在于byte[]中。

你确定编码是ASCII吗?试着在名字中加入一些带有重音的字母,比如àèéìòù。。。也许是UTF8。或者可能是使用CCD_ 7编码。

尝试将servername1-servername12字节添加到byte[12]数组中,并使用从中提取字符串

byte[] array = GetBytesOfServerName();
string serverName = Encoding.ASCII.GetString(array);

如果你可以在项目中使用/ansafe,你可以使用这样的固定缓冲区:

[StructLayout(LayoutKind.Explicit)]
unsafe struct packetrf
{
    [FieldOffset(0)]
    public fixed byte[12] servername;
    [FieldOffset(12)]
    public Int32 imei_msn;
}

这应该有效:

string serverName = Encoding.ASCII.GetString(user.Take(12).ToArray());
string imeiMsn = Encoding.ASCII.GetString(user.Skip(12).ToArray());
Console.WriteLine(serverName);
Console.WriteLine(imeiMsn);