结构到字节数组以通过套接字发送

问题描述 投票:2回答:6

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

.net sockets serialization bytearray struct
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;
    }

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

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

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

如果您愿意照顾字节序(在异类网络中进行通信),则唯一的方法是逐字段进行。

为什么不只使用二进制读取器来填充结构的字段,然后再次读出它们?您只需要了解结构中字段的大小及其在流中的位置即可,无需非托管解决方案。这是我写的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;
    }

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

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

由于您说的是“ struct”,所以我使用的是C语言

您可以使用称为的功能

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

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

您将其用作:

write(socket,&struct_var,sizeof(struct_var));


3
投票

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


1
投票

如果您愿意照顾字节序(在异类网络中进行通信),则唯一的方法是逐字段进行。


1
投票

为什么不只使用二进制读取器来填充结构的字段,然后再次读出它们?您只需要了解结构中字段的大小及其在流中的位置即可,无需非托管解决方案。这是我写的waveplayer的一个示例。


0
投票

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


0
投票

由于您说的是“ struct”,所以我使用的是C语言

© www.soinside.com 2019 - 2024. All rights reserved.