2

从结构中获取字节数组以通过 TCP 套接字发送的最佳方法是什么?我正在使用 .Net(VB 或 C#)。

4

6 回答 6

8

一种选择是将结构的本机表示直接编组到缓冲区中,类似于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;
    }

尽管如此,这是迄今为止最不便携的解决方案。双方都需要使用相同的对齐方式和字节序,如果您需要更改结构本身,则需要自己实现版本控制。

在大多数情况下,您的序列化格式不应该是内部数据结构的直接副本。

于 2009-03-16T15:22:28.733 回答
3

您应该查看Serialization。您可以使用许多选项,从Protocol Buffers(由排名第一和第二的 SO 用户实现)到XmlBinaryFormatter

于 2009-03-16T15:18:25.700 回答
2

为什么不直接使用二进制读取器来填充结构的字段,然后再次读取它们呢?您需要知道的只是结构中字段的大小及其在流中的位置,不需要非托管解决方案。这是我写的 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;
    }
于 2013-10-14T17:07:54.190 回答
1

如果您愿意处理字节序(在异构网络中进行通信),那么做到这一点的唯一方法是逐个字段。

于 2009-03-16T15:10:10.180 回答
0

您需要更具体并告诉我们您的语言。

对于许多语言来说,有现成的框架,甚至是语言标准环境的一部分,可以做这些事情。

于 2009-03-16T15:09:34.880 回答
0

我假设 C 语言,因为你说“结构”

您可以使用一个名为

ssize_t write(int fd, const void *buf, size_t count);

其中 FD 是套接字的文件描述符,缓冲区是结构的地址,count 是字节大小

您可以将其用作:

写(套接字,&struct_var,sizeof(struct_var));

于 2009-03-16T15:11:20.990 回答