Reading binary packet

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • rahul

    Reading binary packet

    I am reading a binary packet : 32, 8, 8, 2, 1, 1, 4, 128
    I am using the following structure to parse the data:
    struct header {
    unsigned int a:32;
    unsigned int b:8;
    unsigned int c:8;
    unsigned int d:2;
    unsigned int e:1;
    unsigned int f:1;
    unsigned int g:4;
    unsigned int h[4];
    };
    struct header head;
    fread (&head, sizeof head, fp);

    My data is getting garbled due to byte ordering differences. The bit
    fieds are giving me incorrect values.
    I suppose that I will have to use/create some byte ordering routines
    ( htonl / ntohl ).
    I tried reading the data in a char array and then coercing it into
    structure pointers so as to avoid multi-byte values but obviously the
    data is dependent on how it is written and not how it is read.
    Is my approach right or is their a better way to do it?
  • vippstar@gmail.com

    #2
    Re: Reading binary packet

    On May 28, 8:40 am, rahul <rahulsin...@gm ail.comwrote:
    I am reading a binary packet : 32, 8, 8, 2, 1, 1, 4, 128
    I am using the following structure to parse the data:
    struct header {
    unsigned int a:32;
    unsigned int b:8;
    unsigned int c:8;
    unsigned int d:2;
    unsigned int e:1;
    unsigned int f:1;
    unsigned int g:4;
    unsigned int h[4];};
    >
    struct header head;
    fread (&head, sizeof head, fp);
    >
    My data is getting garbled due to byte ordering differences. The bit
    fieds are giving me incorrect values.
    If that struct was written to the file previously with a call to
    fwrite(), it should give you the correct result.

    Comment

    • Antoninus Twink

      #3
      Re: Reading binary packet

      On 28 May 2008 at 5:40, rahul wrote:
      I am reading a binary packet : 32, 8, 8, 2, 1, 1, 4, 128
      I am using the following structure to parse the data:
      struct header {
      unsigned int a:32;
      unsigned int b:8;
      unsigned int c:8;
      unsigned int d:2;
      unsigned int e:1;
      unsigned int f:1;
      unsigned int g:4;
      unsigned int h[4];
      };
      struct header head;
      fread (&head, sizeof head, fp);
      fread takes 4 arguments: you need fread (&head, sizeof head, 1, fp);

      You asked in another thread about packing. If you don't tell your
      compiler to pack this struct then it's very likely to include one byte
      of padding between g and h. Use __attribute__(( packed)) in gcc.
      My data is getting garbled due to byte ordering differences. The bit
      fieds are giving me incorrect values.
      It's likely that your compiler is ordering the byte containing d,e,f,g
      like this:

      [ . . . . . . . . ]
      _______ _ _ ___
      g f e d

      So you may need to reorder the bit-fields in your struct.

      If you also need to swap the endianness of your 32-bit fields, you can
      use a macro like this:

      #define CHANGE_END(x) (((x >>24) & 0x000000ff) | ((x >8) & 0x0000ff00) \
      | ((x << 8) & 0x00ff0000) | ((x <<24) & 0xff000000) )

      Comment

      • Keith Thompson

        #4
        Re: Reading binary packet

        rahul <rahulsinner@gm ail.comwrites:
        [...]
        I had to drop the bit fields as the bits are read into a memory
        address and '&' operator is not applicable for bit fields.
        I initialized all the members as unsigned char. As the standard goes,
        a char is always 1 byte.
        Yes, a char is always 1 byte, but a byte is not always 8 bits.

        But you're probably safe in assuming that it is on most platforms.

        --
        Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
        Nokia
        "We must do something. This is something. Therefore, we must do this."
        -- Antony Jay and Jonathan Lynn, "Yes Minister"

        Comment

        • rahul

          #5
          Re: Reading binary packet

          FYI
          If anyone is looking for a bit library or is just curious about the
          implementation, I got it from here

          This library has 2 small bugs. You need to 0 the memory area before
          reading where the bits are to be read
          or else you will be getting incorrect results. Secondly, it does an
          unnecessary right shift while reading
          multiple bits.

          It takes care of the endian-ness. I am posting it as I think some of
          you might want to comment on the
          implementation.

          Comment

          • Nick Keighley

            #6
            Re: Reading binary packet

            On 28 May, 10:01, Antoninus Twink <nos...@nospam. invalidwrote:
            On 28 May 2008 at  5:40, rahul wrote:
            I am reading a binary packet :  32, 8, 8, 2,  1, 1, 4, 128
            I am using the following structure to parse the data:
            struct header {
               unsigned int a:32;
               unsigned int b:8;
               unsigned int c:8;
               unsigned int d:2;
               unsigned int e:1;
               unsigned int f:1;
               unsigned int g:4;
               unsigned int h[4];
            };
            struct header head;
            <snip>
            You asked in another thread about packing. If you don't tell your
            compiler to pack this struct then it's very likely to include one byte
            of padding between g and h. Use __attribute__(( packed)) in gcc.
            it is best to avoid non-portable constructs like this. Other
            suggestions
            of bit stream libraries etc. are a better way to go

            <snip>


            --
            Nick Keighley

            Comment

            • Ben Bacarisse

              #7
              Re: Reading binary packet

              rahul <rahulsinner@gm ail.comwrites:
              FYI
              If anyone is looking for a bit library or is just curious about the
              implementation, I got it from here

              This library has 2 small bugs. You need to 0 the memory area before
              reading where the bits are to be read
              or else you will be getting incorrect results. Secondly, it does an
              unnecessary right shift while reading
              multiple bits.
              >
              It takes care of the endian-ness. I am posting it as I think some of
              you might want to comment on the
              implementation.
              It does things in what is, to me, a slightly odd way. The only places
              where endianness matters (for this library at least) is when reading
              integer values larges than one byte. The author has chosen to do this
              by exposing the endianness and using explicit multi-byte arrays. It
              is much simpler (usually) to do arithmetic on the desired result type.
              That method is fully portable whereas the method used by this library
              works only on systems that have been catered for by the programmer (he
              considers only two orders). I have written C on a machine where this
              would break but of course such machines are rare nowadays, probably
              because so much C code breaks on them.

              --
              Ben.

              Comment

              Working...