Question

What is the best way to get a byte array from a struct to send over TCP sockets? I'm using .Net (VB or C#).

Was it helpful?

Solution

If you're using C#, you can also marshal it to a native buffer yourself, to have better control over serialization.

You would need to add the appropriate attribute to your struct,

  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack=1)]

Then you can serialize it using:

    /// <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;
    }

OTHER TIPS

You should look into Serialization. There are number of options available to you, from Protocol Buffers (implementations by the 1st and 2nd ranked SO users) to Xml to the BinaryFormatter.

If you are willing to take care of the endian (to communicate in an heterogeneous network), the only way to do this is field by field.

Why not just use a binary reader to populate fields of the struct, and read them out again? All you need to know is the size of the fields in the struct and it's position in the stream, no need for unmanaged solutions.. Here's an example from a waveplayer I wrote..

    /// <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;
    }

You need to be more specific and tell us your language.

For many languages, there are ready-made frameworks, or even parts of the language's standard environment, for doing these kinds of things.

I'm assuming the C language since you say "struct"

you can use a function called

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

where FD is the filedescriptor of socket the buffer is the address of the structure, and count is the size in bytes

you would use it as:

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top