当前位置: 代码迷 >> C# >> C#经过socket发送结构体
  详细解决方案

C#经过socket发送结构体

热度:96   发布时间:2016-05-05 03:44:19.0
C#通过socket发送结构体
如题,我想通过socket发送结构体,譬如结构体封装如下:
public struct Operator//定义一个结构体Operator
        {

            public int Int_Value;
            public string Str_Value;
            public bool Bool_Value;
            public float Float_Value;
        }
,我想知道如何将这个结构体封装到一个byte[],然后服务器端再将这个byte[]解析。按上面的顺序,C++有指针可以通过移位方式操作byte[],在C#中我应该怎么做,求大神指教。
------解决思路----------------------
你这个不行,必须规定字段的长度,自己看看Marshal

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
    public struct MinuteDataItem
    {
        [MarshalAs(UnmanagedType.I4)]
        private int timeStamp;

        [MarshalAs(UnmanagedType.R4)]
        private float lastPx;

        [MarshalAs(UnmanagedType.R4)]
        private float averagePx;

        [MarshalAs(UnmanagedType.R4)]
        private float amount;

        [MarshalAs(UnmanagedType.R4)]
        private float volume;
    }

------解决思路----------------------
  [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    public struct MSG_HEAD
    {
        public int len;
        public CMD cmd;
    }

/// <summary>
        /// 结构体转byte数组
        /// </summary>
        /// <param name="structObj">要转换的结构体</param>
        /// <returns>转换后的byte数组</returns>
        public byte[] StructToBytes(object structObj)
        {
            //得到结构体的大小
            int size = Marshal.SizeOf(structObj);
            //创建byte数组
            byte[] bytes = new byte[size];
            //分配结构体大小的内存空间
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将结构体拷到分配好的内存空间
            Marshal.StructureToPtr(structObj, structPtr, false);
            //从内存空间拷到byte数组
            Marshal.Copy(structPtr, bytes, 0, size);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            //返回byte数组
            return bytes;
        }
------解决思路----------------------
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Text;

namespace WindowsFormsApplication3
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Operator op = new Operator();
            op.Int_Value = 1;
            op.Str_Value = "中国2345234";
            op.Bool_Value = false;
            op.Float_Value = 0.123f;

            Byte[] buffer = new Byte[op.Size];

            op.Write(buffer);

            Operator newOp = Operator.Read(buffer);
            MessageBox.Show(newOp.Str_Value);
        }
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct Operator
    {
        public int Int_Value;
        public string Str_Value;
        public bool Bool_Value;
        public float Float_Value;

        public Int32 Size
        {
            get
            {
                Int32 size = sizeof(int) + sizeof(bool) + sizeof(float) + 4;

                if (!String.IsNullOrEmpty(Str_Value))
                {
                    size += Encoding.UTF8.GetBytes(Str_Value).Length;
                }

                return size;
            }
        }

        public void Write(Byte[] buffer)
        {
            int offset = 0;

            BufferHelper.Write(buffer, Int_Value, ref offset);
            BufferHelper.Write(buffer, Str_Value, ref offset);
            BufferHelper.Write(buffer, Bool_Value, ref offset);
            BufferHelper.Write(buffer, Float_Value, ref offset);
        }

        public static Operator Read(Byte[] buffer)
        {
            int offset = 0;
            Operator op = new Operator();

            op.Int_Value = BufferHelper.ReadInt32(buffer, ref offset);
            op.Str_Value = BufferHelper.ReadString(buffer, ref offset);
            op.Bool_Value = BufferHelper.ReadBoolean(buffer, ref offset);
            op.Float_Value = BufferHelper.ReadFloat(buffer, ref offset);

            return op;
        }
    }

    public class BufferHelper
    {
        public static void Write(Byte[] buffer, Int32 value, ref Int32 offset)
        {
            byte[] bTemp = BitConverter.GetBytes(value);
            for (Int32 i = 0; i < bTemp.Length; i++)
            {
                buffer[offset++] = bTemp[i];
            }
        }

        public static Int32 ReadInt32(Byte[] buffer, ref Int32 offset)
        {
            Int32 value = BitConverter.ToInt32(buffer, offset);

            offset += 4;

            return value;
        }

        public static void Write(Byte[] buffer, float value, ref Int32 offset)
        {
            byte[] bTemp = BitConverter.GetBytes(value);
            for (Int32 i = 0; i < bTemp.Length; i++)
            {
                buffer[offset++] = bTemp[i];
            }
        }

        public static Single ReadFloat(Byte[] buffer, ref Int32 offset)
        {
            Single value = BitConverter.ToSingle(buffer, offset);

            offset += 4;

            return value;
        }

        public static void Write(Byte[] buffer, bool value, ref Int32 offset)
        {
            byte[] bTemp = BitConverter.GetBytes(value);
            for (Int32 i = 0; i < bTemp.Length; i++)
            {
                buffer[offset++] = bTemp[i];
            }
        }

        public static Boolean ReadBoolean(Byte[] buffer, ref Int32 offset)
        {
            Boolean value = BitConverter.ToBoolean(buffer, offset);

            offset += 1;

            return value;
        }

        public static void Write(Byte[] buffer, String value, ref Int32 offset)
        {
            if (!String.IsNullOrEmpty(value))
            {
                byte[] bTemp = Encoding.UTF8.GetBytes(value);

                Write(buffer, bTemp.Length, ref offset);
                for (Int32 i = 0; i < bTemp.Length; i++)
                {
                    buffer[offset++] = bTemp[i];
                }
            }
            else
            {
                Write(buffer, 0, ref offset);
            }
        }

        public static String ReadString(Byte[] buffer, ref Int32 offset)
        {
            Int32 len = ReadInt32(buffer, ref offset);

            String str = String.Empty;

            if (len > 0)
            {
                Byte[] bTemp = new Byte[len];
                Buffer.BlockCopy(buffer, offset, bTemp, 0, len);
                offset += len;

                str = Encoding.UTF8.GetString(bTemp);
            }
            return str;
        }
    }
}


随便写了一个
主要就是String,前面先接上4字节的长度
还有更高效的直接拷贝内存的方法

  相关解决方案