C#通过socket发送结构体

叨叨猫 2012-11-28 09:33:06
如题,我想通过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#中我应该怎么做,求大神指教。
...全文
801 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
lijunjingwei 2015-05-18
  • 打赏
  • 举报
回复
飘过 飘过 飘过 飘过
SocketUpEx 2012-11-28
  • 打赏
  • 举报
回复
5楼的代码 直接拷贝就能用
叨叨猫 2012-11-28
  • 打赏
  • 举报
回复
7楼能否把代码你写的这段代码给我,让我看看,QQ:364573294
SocketUpEx 2012-11-28
  • 打赏
  • 举报
回复
另外,推荐Google的protobuf组件
叨叨猫 2012-11-28
  • 打赏
  • 举报
回复
我先看看啊!在此先谢谢了
SocketUpEx 2012-11-28
  • 打赏
  • 举报
回复
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字节的长度 还有更高效的直接拷贝内存的方法
wxm3630478 2012-11-28
  • 打赏
  • 举报
回复
看需求好像是 发送方:发送一个结构体 接收方:解析,得到一个结构体 用序列化和反序列化 先把Operator序列化,转换成byte[],通过Socket发送,然后用反序列化,把byte[]数组转换成Operator
叨叨猫 2012-11-28
  • 打赏
  • 举报
回复
[quote=引用 1 楼 bdmh 的回复:] 你这个不行,必须规定字段的长度,自己看看Marshal C#除了用Marshal有没有别的方法?
sinodzh 2012-11-28
  • 打赏
  • 举报
回复
[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; }
bdmh 2012-11-28
  • 打赏
  • 举报
回复
你这个不行,必须规定字段的长度,自己看看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;
    }
风吹腚腚凉 2012-11-28
  • 打赏
  • 举报
回复
引用 1 楼 bdmh 的回复:
你这个不行,必须规定字段的长度,自己看看Marshal C# code? 12345678910111213141516171819 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)] public struct MinuteDataItem { ……
我一般用这个
assky124 2012-11-28
  • 打赏
  • 举报
回复
把结构体封装成JSON或者XML格式字符传,然后用UTF8转成byte 数组
叨叨猫 2012-11-28
  • 打赏
  • 举报
回复
其实我发现在处理这个结构体时,最重要的还是在处理结构体内部的string的难度有点大。
KJ_Wang 2012-11-28
  • 打赏
  • 举报
回复
进行系列化,理想很多(用类用结构都无所谓)

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧