2

Here are declarations of what I am sending to my server:

typedef enum 
{
    GET = 0,
    SET = 1,
    UNDEF = 2,

} cmd_t;

struct  args 
{ 
    cmd_t cmd; 
    uint8_t value; 
    uint8_t id;
};

value is of type uint8_t and has for example value 42 and id is also uint8_t and has value 30. cmd is my typedef and is for example GET also 0.

I send this info to server packed like this:

char buff[2];
buff[0] = arguments.cmd;
buff[0] += arguments.id << 2;

buff[1] = arguments.value;
send(sfd, buff, sizeof(buff), 0);

I pack in the first byte on the first 2 bits my cmd, then shift it 2 bits and pack the id. Then on the second byte I pack value. I know that value can't be bigger than 127 so I can leave it on the first 7 bits of my byte. I also know that id can't be greather that 63.

Here is what I mean:

Then I receive that on my server. When I read second byte of my response also req[1] I get value 42, but when I read my first byte also req[0] however I shift it I can't get 0 or 30. req is delared as req[2]. Here is what I tried:

    for (size_t i = 0; i < 8; i++)
    {
       int idCMD = (uint8_t) (req[0]>>i);
       printf("idCMD -> %d\n", idCMD);
    }
    printf("\n");
     for (size_t i = 0; i < 8; i++)
    {
       int idCMD = (uint8_t) (req[0]<<i);
       printf("idCMD -> %d\n", idCMD);
    }

How do I read my cmd and id?

output:

    idCMD -> 121
    idCMD -> 60
    idCMD -> 30
    idCMD -> 15
    idCMD -> 7
    idCMD -> 3
    idCMD -> 1
    idCMD -> 0

    idCMD -> 121
    idCMD -> 242
    idCMD -> 228
    idCMD -> 200
    idCMD -> 144
    idCMD -> 32
    idCMD -> 64
    idCMD -> 128

What I got out of this is that:

    printf("value -> %d\n", req[1]);
    printf("id -> %d\n", req[0] >> 2);
    printf("cmd-> %d\n", req[0] >> 6);

    value -> 42
    id -> 30
    cmd-> 1

I get that cmd is 1 also. How do I make sure that I read 0 and not 1?

but it seems that I am not reading my cmd right. The output above is when the cmd is 1. Here is when the cmd is 0 and value 0:

idCMD -> 120
idCMD -> 60
idCMD -> 30
idCMD -> 15
idCMD -> 7
idCMD -> 3
idCMD -> 1
idCMD -> 0

idCMD -> 120
idCMD -> 240
idCMD -> 224
idCMD -> 192
idCMD -> 128
idCMD -> 0
idCMD -> 0
idCMD -> 0
value -> 0
id -> 30
cmd-> 1

How do I read cmd correctly and is this correct interpretation?

cheshire
  • 1,109
  • 3
  • 15
  • 37

2 Answers2

1

Here you are

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef enum 
{
    GET = 0,
    SET = 1,
    UNDEF = 2,

} cmd_t;

struct  args 
{ 
    cmd_t cmd; 
    uint8_t value; 
    uint8_t id;
};

int main(){
    char buff[2];
    struct  args arguments;
    arguments.cmd=UNDEF;
    arguments.id=23;//256/4=64 range 0~63



    buff[0] = arguments.cmd;
    buff[0] += arguments.id << 2;
    buff[1] = arguments.value;



    printf("%d\n",buff[0]&0b11);
    printf("%d",(buff[0]&0b11111100)>>2);
    return 0;
}
J CHEN
  • 494
  • 3
  • 9
-1

If you just want easy way,this is another choose union+struct

you can define how many bits per member in struct

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef enum 
{
    GET = 0,
    SET = 1,
    UNDEF = 2,

} cmd_t;


union args_v2{
    uint8_t raw[2];

    struct {
        uint8_t cmd: 2;//2bits
        uint8_t id: 6;//6bits
        uint8_t value:  8;//8bits
    };
};
int main(){


    union args_v2 arguments_2;
    arguments_2.id=32;
    arguments_2.cmd=UNDEF;
    arguments_2.value=77;
    printf("\nPack Size%d\n",sizeof(arguments_2));
    printf("\nRaw %d %d\n",arguments_2.raw[0],arguments_2.raw[1]);//130=32*4+2
    //
    printf("\nid:%d cmd:%d value:%d\n",arguments_2.id,arguments_2.cmd,arguments_2.value);





    return 0;
}
J CHEN
  • 494
  • 3
  • 9
  • I don't think using structs/unions/bitfields is a good idea for a network protocol, since if the client and server are running on different systems (or were built with different compilers), they may not be using the same layout, and then everything breaks. – Nate Eldredge Dec 02 '19 at 13:48
  • you think little endian problem , so i declare using uint8_t array not uint16_t,so never cause your problem – Nate Eldredge – J CHEN Dec 03 '19 at 03:12
  • I have experience about this – J CHEN Dec 03 '19 at 03:14
  • I don't think that helps. ["The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined"](https://stackoverflow.com/questions/1490092/c-c-force-bit-field-order-and-alignment). You simply can't guarantee that any two compilers will lay out your struct in the same way. Maybe most common compilers will do so, in this case, but I still don't think it's a good practice in general. – Nate Eldredge Dec 03 '19 at 12:04
  • thats why i use uint_8 not uint_16 – J CHEN Dec 04 '19 at 02:57
  • i dont what argue any more about this – J CHEN Dec 04 '19 at 02:59