将字节数组转换为struct时的异常

时间:2015-11-13 19:26:08

标签: c# struct casting

我有用C编写的服务器应用程序,必须发送截图throguh socket和c#gui客户端。问题是由于异常,我无法将字节数组转换为结构。在C / C ++中将char数组转换为struct很简单,但在c#中却不那么简单。这是测试代码:

public partial class Form1 : Form
    {
        const int magic = 101;
        enum command {GET_SCREEN = 1, MOVE_MOUSE, CLICK_MOUSE };

        public struct send_packet
        {
            public int magic;
            public int cmd;

        };

        public struct recv_packet
        {
            public int magic;
            public int code;
            public int length;
            public byte[] body;

        };
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            int port = 4000;
            TcpClient client = new TcpClient("127.0.0.1", 4000);
            NetworkStream nws = client.GetStream();
            BinaryWriter bw = new BinaryWriter(nws);
            BinaryReader br = new BinaryReader(nws);
            byte[] buff = new byte[512];

            send_packet pkt = new send_packet();
            pkt.magic = magic;
            pkt.cmd = (int)command.GET_SCREEN;
            while (true)
            {

                bw.Write(pkt.magic);
                bw.Write(pkt.cmd);

                br.Read(buff, 0, 512);
                GCHandle pinnedPacket = GCHandle.Alloc(buff, GCHandleType.Pinned);
                recv_packet rcv_pkt = (recv_packet)Marshal.PtrToStructure(pinnedPacket.AddrOfPinnedObject(), typeof(recv_packet));
                //string str = System.Text.Encoding.Default.GetString(rcv_pkt.length);
                string str = rcv_pkt.length.ToString();
                MessageBox.Show(str);


            }

        }
    }

它可能是什么?异常的文本是俄语,但有最重要的信息:" System.AccessViolationException"在mscorlib.dll中,尝试读取或写入受保护的内存。这样的事情。它发生在这个字符串recv_packet rcv_pkt = (recv_packet)Marshal.PtrToStructure(pinnedPacket.AddrOfPinnedObject(), typeof(recv_packet));

我已经解释了为什么这不起作用以及一种解决方案https://social.msdn.microsoft.com/Forums/vstudio/en-US/3c152957-91e7-43bf-91de-a047a3d124f5/exception-when-converting-byte-array-to-structure?forum=csharpgeneral

1 个答案:

答案 0 :(得分:-1)

    //Functions to turn byte arrays to structs. 

    public static byte[] RawSerialize<T>(T frqStruct)
    where T : struct
    {
        int rawsize = Marshal.SizeOf<T>();

        IntPtr i = IntPtr.Zero;
        try
        {
            i = Marshal.AllocHGlobal(rawsize);
            Marshal.StructureToPtr<T>(frqStruct, i, false);
            byte[] rawdatas = new byte[rawsize];
            Marshal.Copy(i, rawdatas, 0, rawsize);
            return rawdatas;
        }
        finally
        {
            if (i != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(i);
            }
        }
    }

    public static T RawDeserialize<T>(byte[] bytearray)
    where T : struct
    {
        int len = Marshal.SizeOf<T>();

        IntPtr i = IntPtr.Zero;
        try
        {
            i = Marshal.AllocHGlobal(len);

            Marshal.Copy(bytearray, 0, i, len);

            return Marshal.PtrToStructure<T>(i);
        }
        finally
        {
            if (i != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(i);
            }
        }
    }

像这样使用

 Struct struct1=new Struct();
 byte[] outarr = RawSerialize(struct1);

struct1 = RawDeserialize<Struct>(outarr);

还要确保您的结构声明正确(大小等):

[StructLayout(LayoutKind.Sequential, Size = 24)]
public struct myStruct
{
    public byte byte1;
    public byte byte2;
    public ushort reserved;
    //Was char[16]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
    public string name; // null terminated

    public uint version;
}