从结构中获取字节数组以通过 TCP 套接字发送的最佳方法是什么?我正在使用 .Net(VB 或 C#)。
6 回答
一种选择是将结构的本机表示直接编组到缓冲区中,类似于memcpy
在 C 中的工作方式。
您需要将适当的属性添加到您的结构中,
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack=1)]
然后您可以使用以下方法对其进行序列化:
/// <summary>
/// Serializes the specified object into a byte array.
/// </summary>
/// <param name="nativeObject">The object to serialize.</param>
/// <returns></returns>
public static byte[] Serialize(object obj)
{
Type objectType = obj.GetType();
int objectSize = Marshal.SizeOf(obj);
IntPtr buffer = Marshal.AllocHGlobal(objectSize);
Marshal.StructureToPtr(obj, buffer, false);
byte[] array = new byte[objectSize];
Marshal.Copy(buffer, array , 0, objectSize);
Marshal.FreeHGlobal(buffer);
return array;
}
尽管如此,这是迄今为止最不便携的解决方案。双方都需要使用相同的对齐方式和字节序,如果您需要更改结构本身,则需要自己实现版本控制。
在大多数情况下,您的序列化格式不应该是内部数据结构的直接副本。
您应该查看Serialization。您可以使用许多选项,从Protocol Buffers(由排名第一和第二的 SO 用户实现)到Xml到BinaryFormatter。
为什么不直接使用二进制读取器来填充结构的字段,然后再次读取它们呢?您需要知道的只是结构中字段的大小及其在流中的位置,不需要非托管解决方案。这是我写的 waveplayer 的一个例子。
/// <summary>Copies header to a stream</summary>
/// <param name="waveData">Wav data stream</param>
/// <param name="format">WAVEFORMATEX wav format</param>
/// <returns>Stream</returns>
public Stream CreateStream(Stream waveData, WAVEFORMATEX format)
{
MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(System.Text.Encoding.ASCII.GetBytes("RIFF".ToCharArray()));
writer.Write((Int32)(waveData.Length + 36)); //File length minus first 8 bytes of RIFF description
writer.Write(System.Text.Encoding.ASCII.GetBytes("WAVEfmt ".ToCharArray()));
writer.Write((Int32)16); //length of following chunk: 16
writer.Write((Int16)format.wFormatTag);
writer.Write((Int16)format.nChannels);
writer.Write((Int32)format.nSamplesPerSec);
writer.Write((Int32)format.nAvgBytesPerSec);
writer.Write((Int16)format.nBlockAlign);
writer.Write((Int16)format.wBitsPerSample);
writer.Write(System.Text.Encoding.ASCII.GetBytes("data".ToCharArray()));
writer.Write((Int32)waveData.Length);
waveData.Seek(0, SeekOrigin.Begin);
byte[] b = new byte[waveData.Length];
waveData.Read(b, 0, (int)waveData.Length);
writer.Write(b);
writer.Seek(0, SeekOrigin.Begin);
return stream;
}
如果您愿意处理字节序(在异构网络中进行通信),那么做到这一点的唯一方法是逐个字段。
您需要更具体并告诉我们您的语言。
对于许多语言来说,有现成的框架,甚至是语言标准环境的一部分,可以做这些事情。
我假设 C 语言,因为你说“结构”
您可以使用一个名为
ssize_t write(int fd, const void *buf, size_t count);
其中 FD 是套接字的文件描述符,缓冲区是结构的地址,count 是字节大小
您可以将其用作:
写(套接字,&struct_var,sizeof(struct_var));