0

I'm sending some packets of data across the network and they arrive in byte[]s, lets say the structure is

[int, int, byte, int]

If this was c++ I would declare a struct* and point to the byte[]. I'm doing this project in c# and I'm not sure whether it is worth it with marshalling overhead, or if there is a better way to handle it in c#, I'm all ears.

  • update, for clarity

Basically, what he is doing Marshaling a Byte array to a C# structure Except I'm wondering if it is worth it.

Community
  • 1
  • 1
dpington
  • 1,844
  • 3
  • 17
  • 29
  • What function are you passing this byte array to? Can you show us the rest of the code? I'm having difficulty conceptualizing what exactly you're trying to accomplish. (And how you get a `byte[]` from a struct that contains a `byte`.) – Cody Gray - on strike Jun 04 '11 at 14:04

4 Answers4

0

I think marshaling is the best option. You could parse the byte array by yourself using BitConverter, but that would require more work on your part and is not as flexible.

svick
  • 236,525
  • 50
  • 385
  • 514
0

The only real reason to do it that way would be to squeeze every last bit of performance out of the system. In my opinion, you're better off writing it using BitConverter to make sure it's working. Then, if getting the data is a performance bottleneck, consider doing the marshaling.

For example, given a struct:

struct MyStruct
{
    private int f1;
    private int f2;
    private byte f3;
    private int f4;
    public MyStruct(int i1, int i2, byte b1, int i4)
    {
        f1 = i1;
        f2 = i2;
        f3 = b1;
        f4 = i4;
    }
    // assume there are public get accessors
}

Then you can get create a new one from the buffer with:

var s = new MyStruct(BitConverter.ToInt32(buff, 0),
    BitConverter.ToInt32(buff, 4),
    BitConverter.ToUInt8(buff, 8),
    BitConverter.ToInt32(buff, 9));

That's a whole lot easier to write and verify than the marshaling, and probably will be fast enough for your needs.

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
  • It is quite a bother making sure the offsets are right and with variable length data and more than 4 fields for the protocol. – dpington Jun 04 '11 at 14:32
0

Well, I guess everyone has their own 'favourite' way. When receiving protocol units over a byte stream in any OO language, I usually fire every received byte into a 'ProtocolUnit' class instance by calling its 'bool addByte() method. A state-machine in the class handles the bytes and error/sanity checks the assembled fields. If a ProtocolUnit has been received in its entirety, the addByte() method function returns true to indicate to the caller that a PDU has been correctly assembled. Usually, the instance is then queued off to whatever is going to handle it and a new ProtocolUnit created, (or depooled), so it can start to assemble the next PDU.

It's implicit that the start of a message can be identified so that, in case of an error, the state-machine can either reset itself, so dumping the erroneous data, or by returning 'true' to the addByte() call, setting a suitable errorMessage that the caller can check to decide what to do, (eg. if the errorMess property is "" then queue to handler else queue to error logger).

I'm sure that you consider this a massive overkill, but it works for me :)

Rgds, Martin

PS try to avoid protocols where the length is transmitted at the start and is the only way to identify message start/end. This is very fragile and prone to explosions, especially with non-secure transports like UDP. Even with TCP, I have known a x****x router that would occasionally add a null to packets...

Martin James
  • 24,453
  • 3
  • 36
  • 60
0

As an alternative to BitConverter, wrap every byte[] in a MemoryStream, and extract the fields using a BinaryReader. Similar, but the stream maintains the offsets for you.

anton.burger
  • 5,637
  • 32
  • 48