networking - Issue receiving and storing data in C++ -
i have written server application in c++ receives packet of data client application (which have not written myself) , prints data console. issue is, when try receive , store entire packet body @ once, data stored incorrectly, when packet body received , stored using multiple callings of recv(), store correctly.
regarding endianness, client , server both running on little endian machine, client sends data out little endian, , server reads without need conversion.
this packet client application sends server application:
00 03 23 00 57 6f 57 00 01 0c 01 f3 16 36 38 78 00 6e 69 57 00 42 47 6e 65 00 00 00 00 7f 00 00 01 05 41 44 4d 49 4e
here structured view of packet:
cmd 00 error 03 pkt_size 23 00 gamename 57 6f 57 00 version1 01 version2 0c version3 01 build f3 16 platform 36 38 78 00 os 6e 69 57 00 country 42 47 6e 65 timezone_bias 00 00 00 00 ip 7f 00 00 01 srp_i_len 05 srp_i 41 44 4d 49 4e
these expected results printed out server application:
cmd: 0 error: 3 pkt_size: 35 gamename: 5730135 version1: 1 version2: 12 version3: 1 build: 5875 platform: 7878710 os: 5728622 country: 1701726018 timezone_bias: 0 ip: 127 0 0 1 srp_i_len: 5 srp_i: admin
here code having trouble with:
struct packet{ uint8 cmd; uint8 error; uint16 pkt_size; uint32 gamename; uint8 version1; uint8 version2; uint8 version3; uint16 build; uint32 platform; uint32 os; uint32 country; uint32 timezone_bias; uint8 ip[4]; uint8 srp_i_len; uint8 srp_i[16]; }; packet data; recv(clientsocket, &data.cmd, 4, 0); // receive packet header recv(clientsocket, &data.gamename, 46, 0); // receive packet body printf("%d\n", data.cmd); ... printf("%s\n", data.srp_i);
the result:
cmd: 0 error: 3 pkt_size: 35 gamename: 5730135 version1: 1 version2: 12 version3: 1 build: 13846 (this goes wrong) platform: 1466527232 os: 1850163712 country: 101 timezone_bias: 35512 ip: 1 5 65 68 srp_i_len: 77 srp_i: in
if change code so:
recv(clientsocket, &data.cmd, 4, 0); // receive packet header recv(clientsocket, &data.gamename, 7, 0); // receive packet body recv(clientsocket, &data.build, 39, 0); // receive packet body
the result:
... same expected results build: 5875 (fixed) platform: 1768816760 (goes wrong here instead) os: 1195507799 country: 25966 timezone_bias: 8323072 ip: 0 1 5 65 srp_i_len: 68 srp_i: min
and if make 1 last adjustment code, so:
recv(clientsocket, &data.cmd, 4, 0); // receive packet header recv(clientsocket, &data.gamename, 7, 0); // receive packet body recv(clientsocket, &data.build, 2, 0); // receive packet body recv(clientsocket, &data.platform, 37, 0); // receive packet body
the result:
... same expected results build: 5875 platform: 7878710 os: 5728622 country: 1701726018 timezone_bias: 0 ip: 127 0 0 1 srp_i_len: 5 srp_i: admin
by calling recv() multiple times, received , stores data expected. have absolutely no idea why data stored incorrectly when calling recv() twice. please, somebody, enlighten me. thank you.
ps: sorry monster post of ugliness.
declare structure packed structure avoid alignment issues;
on windows use #pragma pack (1)
(see msdn)
on gcc use __attribute__((packed))
to remove alignment problems. gcc support windows style pragmas compatibility. have at:
http://gcc.gnu.org/onlinedocs/gcc/structure_002dpacking-pragmas.html
edit
so example code below shows 1 packed structure inside untouched structure:
when compiled on x86_64-bit platform:
#include <iostream> #include <stdint.h> #include <string.h> using namespace std; uint8_t input[] = { 0x00, 0x03, 0x23, 0x00, 0x57, 0x6f, 0x57, 0x00, 0x01, 0x0c, 0x01, 0xf3, 0x16, 0x36, 0x38, 0x78, 0x00, 0x6e, 0x69, 0x57, 0x00, 0x42, 0x47, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x01, 0x05, 0x41, 0x44, 0x4d, 0x49, 0x4e }; struct __attribute__((packed)) packet{ uint8_t cmd; uint8_t error; uint16_t pkt_size; uint32_t gamename; uint8_t version1; uint8_t version2; uint8_t version3; uint16_t build; uint32_t platform; uint32_t os; uint32_t country; uint32_t timezone_bias; uint8_t ip[4]; uint8_t srp_i_len; uint8_t srp_i[16]; }; struct data { long int foo; short a; uint8_t b; struct packet p; uint32_t bar; }; int main() { struct packet p; struct data d; cout << "in: " << sizeof(input) << ", d: " << sizeof (d) << ", p: " << sizeof(p) << " d.p: " << sizeof(d.p) << endl; memset(&p, 0, sizeof(p)); memcpy(&p, input, sizeof(input)); cout << (int) p.srp_i_len << endl; cout << p.srp_i << endl; } $./foo in: 39, d: 72, p: 50 d.p: 50 5 admin
Comments
Post a Comment