0

I am transferring a struct over socket using c++. I read some earlier questions on sending structs and one approach suggested was to transfer using a char* after cast. Since both server and client are on same machine so no issues of endianness here.

Couple of questions here. I get size of struct as 48. As per my calculation shouldn't it be 43? 8x4 + 10 +1

Secondly on server side when i print the received buffer I only get the text elements. The long integers are not received.

struct testStruct{
    char type;
    char field1[10];
    char field2[8];
    char field3[8];
    long num1, num2;
};


    testStruct ls;
    ls.type = 'U';

    strcpy(ls.field1, "NAVEENSHAR");
    strcpy(ls.field2, "abcd1234");
    strcpy(ls.field3, "al345678");
    ls.num1 = 40;
    ls.num2 = 200;
    char* bytes = static_cast<char*>(static_cast<void*>(&ls));
    bytes_sent = send(socketfd, bytes, sizeof(ls), 0);
    cout << "bytes sent: " << bytes_sent<< "\n";

    //On server sidechar
    incomming_data_buffer[1000];
    bytes_recieved = recv(new_sd, incomming_data_buffer,1000, 0);
    cout << "|" << incomming_data_buffer << "|\n";

It shows 48 bytes received and no trailing integers which i added. Any idea on why this could be happening. I have read about sending structs using boost serialization but at the same time that overhead is huge for simple structs.

Naveen Sharma
  • 1,057
  • 12
  • 32
  • 1
    `sizeof(testStruct)` is 48 [because of alignment](http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member). The `long`s have to be aligned on a `sizeof(long)` boundary, which apparently is 8 bytes on your machine. `char`s on the other hand, only need to be aligned 1-byte. You have 27 bytes for the first four members, so the compiler has to add extra padding (5 bytes) between `field3` and `long` for alignment to work. So 27+5 bytes = 32 bytes, providing the proper alignment for the two `long`s (and explains the 5-byte discrepancy). – In silico Sep 13 '14 at 07:35
  • 1
    Note also that your string fields are too small for the strings you are copying to them - evidently you didn't allow for the \0 terminator. Use strcpy in future to avoid memory corruption when you make this kind of mistake. – Paul R Sep 13 '14 at 07:44
  • @PaulR, is \0 necessary? I am using `strcpy` only? Didn't understand what you meant. – Naveen Sharma Sep 13 '14 at 07:54
  • C strings always have a terminating \0, so e.g. "abcd1234" is actually 9 characters, all of which will be copied by strcpy, and therefore writing beyond the end of your 8 character string `field2`. – Paul R Sep 13 '14 at 09:19
  • @PaulR, thanks, I changed to memcpy. that should do it. – Naveen Sharma Sep 13 '14 at 11:42
  • That will work for now, but a better solution would be to make your string fields larger and use strncpy to prevent buffer overflows. – Paul R Sep 13 '14 at 11:47
  • @PaulR, Thing is server has specified this format of 10, 8, 8. can't say for sure if it will accept the longer values. will try though. – Naveen Sharma Sep 13 '14 at 11:49
  • OK - in that case keep the buffer sizes but use `strncpy` to prevent overflow. – Paul R Sep 13 '14 at 11:54

1 Answers1

2

You are almost certainly receiving all the data. The problem is with this line:

cout << "|" << incomming_data_buffer << "|\n";

which prints incomming_data_buffer as a C style string, so stops at the first zero-byte. Since your long values are encoded in binary for, there will be zeros at least there (there may also be zeros in the padding between fields).

You could try doing something like:

cout << "|";
for (int i = 0; i < bytes_received; i++)
{
    cout << hex << (((int)incomming_data_buffer[i]) & 0xff) << " ";
}
cout << "|\n";

to show all bytes of the package you received.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • I tried this but get some weird cout errors that `invalid operands of type int and char[2] for operator <<` – Naveen Sharma Sep 13 '14 at 11:41
  • Need another set of parenthesis around the math expression with the `& 0xff`. Now edited. – Mats Petersson Sep 13 '14 at 17:25
  • I see all the bytes received but I think server wants the long to start immediately post third char field. Is there any way to achieve that and avoid padding? – Naveen Sharma Sep 14 '14 at 06:59
  • Your best option is probably to write some code that serializes the data into a buffer of bytes. Although there are ways that you can make many compilers pack the structure, there are also many processor architectures where reading an unaligned (not padded) piece of data will either lead to incorrect result or a crash. – Mats Petersson Sep 14 '14 at 08:00