【发布时间】:2009-03-16 15:06:27
【问题描述】:
从结构中获取字节数组以通过 TCP 套接字发送的最佳方法是什么?我正在使用 .Net(VB 或 C#)。
【问题讨论】:
-
您的环境是什么(.NET、Java、C/C++)?没有这些信息,什么都做不了。
-
你使用什么编程语言?
标签: .net sockets serialization bytearray struct
从结构中获取字节数组以通过 TCP 套接字发送的最佳方法是什么?我正在使用 .Net(VB 或 C#)。
【问题讨论】:
标签: .net sockets serialization bytearray struct
一种选择是将结构的本机表示直接编组到缓冲区中,类似于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 计数);
其中 FD 是套接字的文件描述符 buffer 是结构体的地址,count 是字节数
您可以将其用作:
写(socket,&struct_var, sizeof(struct_var));
【讨论】: