简体   繁体   English

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

[英]c# using marshalling for packet parsing

I have to parse a packet which is stored in byte[] in ascii code for example byte[] user = new byte[] {112, 114, 97, 116, 121, 117, 115, 104, 0, 0, 0, 0, 49, 50, 51, 0} where first 12 bytes are servername and last four bytes are some id. 我必须在ascii代码中解析存储在byte []中的数据包,例如byte [] user = new byte [] {112,114,97,116,121,117,115,104,0,0,0, 0,49,50,51,0}其中前12个字节是servername,后4个字节是id。

By going through previous stackoverflow posts I came up with this code 通过浏览以前的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);
}

When I run this code my output is 7526488566770266736 for servername and 13106 for imei_msn which is probably is probably ascii->hex->decimal format. 当我运行此代码时,我的输出为servername的7526488566770266736和imei_msn的13106,这可能是ascii-> hex-> decimal格式。 Now the problem I am facing is that how can I convert these numbers to some meaning full information like first one to string showing name and second one to imei_msn in decimal format? 现在我面临的问题是,如何将这些数字转换为某些意义的完整信息,例如第一个字符串显示名称,第二个字符串以十进制格式输入imei_msn?

Try using fixed-size arrays (read here https://stackoverflow.com/a/14629106/613130 ) 尝试使用固定大小的数组(请参阅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;
};

Then from there: 然后从那里:

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

or directly as a property 或直接作为财产

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

And remember to TrimEnd all those '\\0' that there will be in the byte[] . 并记住TrimEnd所有那些'\\0'将存在于byte[]

Are you sure the encoding is ASCII ? 你确定编码是ASCII吗? Try putting in the name some letters with accents, like àèéìòù ... Perhaps it's UTF8 . 尝试在名称中添加一些带重音的字母,例如àèéìòù ......也许它是UTF8 or perhaps it's using the Default encoding. 或者它可能正在使用Default编码。

Try adding your servername1servername12 bytes into a byte[12] array and pull a string out of it by using 尝试将servername1 - servername12字节添加到byte[12]数组中,然后使用将字符串拉出来

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

If you are okay with using /unsafe with your project, you can use fixed buffer like this: 如果您对项目使用/ unsafe没问题,可以使用这样的固定缓冲区:

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

    [FieldOffset(12)]
    public Int32 imei_msn;
}

This should work: 这应该工作:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM