c00ke
c00ke

Reputation: 2315

Structs to Byte Arrays to send over sockets

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#).

Upvotes: 2

Views: 5532

Answers (6)

vgru
vgru

Reputation: 51224

One option is to marshal the native representation of the struct into a buffer directly, similar to how memcpy works in C.

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

Still, this is by far the least portable solution. Both sides will need to use the same alignment and endianness, and you will need to implement versioning yourself if you will ever need to change the struct itself.

In most cases, your serialization format shouldn't be a direct copy of your internal data structures.

Upvotes: 8

JGU
JGU

Reputation: 899

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

Upvotes: 2

Joel Coehoorn
Joel Coehoorn

Reputation: 415790

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.

Upvotes: 3

Jaap Geurts
Jaap Geurts

Reputation: 623

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));

Upvotes: 0

Maurice Perry
Maurice Perry

Reputation: 32831

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.

Upvotes: 1

unwind
unwind

Reputation: 399833

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.

Upvotes: 0

Related Questions