0

I'm sending a c struct with write to a server. The struct and write look like this.

typedef struct MyStruct {
    uint8_t         flag; 
    char            str[50];
    int32_t         number;
    time_t          time; 

} MyStruct ;

...

// Create mystruct

memset(&mystruct->flag,   '\1', sizeof(uint8_t));
memset(&mystruct->str, '\0', sizeof(char) * 50);
memset(&mystruct->number, '\2', sizeof(int32_t)); 
memset(&mystruct->time,   '\3', sizeof(time_t)); 

write(sockfd, mystruct, sizeof(MyStruct)); 

The server, in Java, receives the information in a nio ByteBuffer and then gets a byte[] with ByteBuffer.array. When I examine the byte[] its contents are:

[ 0]         = 1
[ 1] to [50] = 0
[51]         = 70
[52] to [55] = 2
[56] to [63] = 3

If you add the lengths up 1 + 50 + 4 + 8 you get 63, but the length with the odd 70 byte is 64.

Why is the 70 byte here? Does it have something to do with networking or c structs? Also how, if I can, get rid of it?

ezPaint
  • 152
  • 1
  • 8
  • 3
    Please just don't do this. You're asking for a world of pain. If you're going to use a channel that sends streams of bytes, define precisely what the stream of bytes you're going to exchange is. Don't say "I'll send whatever the C struct happens to be and hope it happens to make sense to the other side". – David Schwartz Jun 30 '16 at 18:25
  • Aside, do you realise that `memset(&mystruct->number, '\2', sizeof(int32_t));` sets the variable to `0x02020202`, or decimal `33686018`? – Weather Vane Jun 30 '16 at 18:26
  • @WeatherVane yes, this is just me debugging it. – ezPaint Jun 30 '16 at 18:27

2 Answers2

2

Why is the 70 byte here? Does it have something to do with networking or c structs? Also how, if I can, get rid of it?

It probably has to do with structure padding. You can try and serialize each member of the structure separately if that's the case.

Also here is a post which well explains all the pitfalls with serialization in C.

Serialization in C is more tricky than say in C# or I think also in Java, for example in C# you know that integer is always 4 bytes in size, which is not the case in C, where the size of integer can vary on platforms.

Community
  • 1
  • 1
Giorgi Moniava
  • 27,046
  • 9
  • 53
  • 90
2

It's almost certainly due to structure padding; most likely, your compiler/processor requires 32-bit values to be 32-bit aligned, so since your uint8_t and your char[50] add up to 51 bytes, there's a one-byte pad between str and number.

As was mentioned in the comments - you really want to handle your serialization explicitly. There are a number of libraries that can handle defining Java and C/C++ types, along with methods to serialize/deserialize in each language.

Sbodd
  • 11,279
  • 6
  • 41
  • 42