C# UDP接收结构体数据类型-----只能读取第一个字段的问题

来源:互联网 发布:wordpress整站源码 编辑:程序博客网 时间:2024/06/02 10:12

在C#的UDP接收嵌入式设备端发送的结构体数据时,经过

//声明一个SDK_MSG_DEVICEINFO的结构体
[Serializable] // 指示可序列化
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
//[StructLayout(LayoutKind.Sequential, Pack = 1)] // 按1字节对齐
public struct SDK_MSG_DEVICEINFO
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] // 声明一个字符数组,大小为64
    public string hardware_ver;      //硬件版本
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] // 声明一个字符数组,大小为20
    public string szMacAddr;   //MAC STRING
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] // 声明一个字符数组,大小为32
    public string szUID;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] // 声明一个字符数组,大小为32
    public string szPwd;

};

        ///发送的时候先要把结构转换成字节数组
        /// 将结构转换为字节数组
        /// 结构对象
        /// 字节数组
        public byte[] StructToBytes(object obj)
        {
            //得到结构体的大小
            int size = Marshal.SizeOf(obj);
            //创建byte数组
            byte[] bytes = new byte[size];
            //分配结构体大小的内存空间
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将结构体拷到分配好的内存空间
            Marshal.StructureToPtr(obj, structPtr, false);
            //从内存空间拷到byte数组
            Marshal.Copy(structPtr, bytes, 0, size);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            //返回byte数组
            return bytes;
        }


        //接收的时候需要把字节数组转换成结构 


        /// byte数组转结构
        /// 
        /// byte数组
        /// 结构类型
        /// 转换后的结构
        public object BytesToStruct(byte[] bytes, Type type)
        {
            //得到结构的大小
            int size = Marshal.SizeOf(type);
            //Log(size.ToString(), 1);
            //byte数组长度小于结构的大小
            if (size > bytes.Length)
            {
                //返回空
                return null;
            }
            //分配结构大小的内存空间
            IntPtr structPtr = Marshal.AllocHGlobal(size);


            //将byte数组拷到分配好的内存空间
            Marshal.Copy(bytes, 0, structPtr, size);
            //将内存空间转换为目标结构
            object obj = Marshal.PtrToStructure(structPtr, type);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            //返回结构
            return obj;
        }

        void RecvThread()
        {
            EndPoint ep = (EndPoint)endpoint; 
            while (true)
            {
                byte[] buf =  new byte[1024];
                SDK_MSG_DEVICEINFO deviceinfo = new SDK_MSG_DEVICEINFO();
                int count = sock.ReceiveFrom(buf, ref ep);
                
                Console.WriteLine(">>>>>ip>>" + (ep as IPEndPoint).Address.ToString() +">>>>>port>>>"+ (ep as IPEndPoint).Port.ToString()); // 发送方的IP地址
                deviceinfo = (SDK_MSG_DEVICEINFO)this.BytesToStruct(buf, typeof(SDK_MSG_DEVICEINFO));             
                if (deviceinfo.szUID.Length > 0)
                {
                    if (udpIPaddr.Count < UDP_MAX_VALUE)
                    {
                        String ipstr = (ep as IPEndPoint).Address.ToString();
                        //判断是否List中已经有搜索到的IP,如有跳过
                        if (udpIPaddr.Contains(ipstr) == false)
                        {
                            udpIPaddr.Add(ipstr);
                            Console.WriteLine("deviceinfo.szUID  " + deviceinfo.szUID.ToString());
                            Console.WriteLine("deviceinfo.szPwd  " + deviceinfo.szPwd.ToString());
                            Console.WriteLine("deviceinfo.szMacAddr   " + deviceinfo.szMacAddr.ToString());
                            Console.WriteLine("deviceinfo.hardware_ver  " + deviceinfo.hardware_ver.ToString());
                            sdkMsgDeviceInfo.Add(deviceinfo);
                        }
                    }
                }               
            }
        }

int count = sock.ReceiveFrom(buf, ref ep)接收到的数据长度是正确的,但是打印显示只能获取第一个字段deviceinfo.hardware_ver。

问题解决办法:

将结构体的按8的倍数对齐即可


//声明一个SDK_MSG_DEVICEINFO的结构体
[Serializable] // 指示可序列化
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct SDK_MSG_DEVICEINFO
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)] // 声明一个字符数组,大小为24
    public string szMacAddr;   //MAC STRING
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] // 声明一个字符数组,大小为32
    public string szUID;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] // 声明一个字符数组,大小为32
    public string szPwd;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] // 声明一个字符数组,大小为64
    public string hardware_ver;      //硬件版本
};



0 0
原创粉丝点击