如题,我想通过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字节的长度
还有更高效的直接拷贝内存的方法
