C++ Socket envoi de structures sérialisées
Bonjour a tous,
Dans le cadre d'un projet scolaire je dois coder un serveur tcp qui est censé réceptionner des structures sur le réseau via socket TCP. Je ne suis pas autorisé a utiliser de librairies type Qt ou Boost pour la sérialisation ou pour le réseau.
Mon problème est que les données que je reçoit sont corrompues. Excuser moi pour la longueure du code que je m'apprête a poster mais si vous voulez avoir une chance de m'aider il vous faut tout les éléments.
La structure que j'envoie ( c'est Packet) :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
struct Header
{
uint32_t magic;
uint32_t checksum;
uint32_t timestamp;
uint16_t commandId;
uint16_t dataSize;
};
struct Packet
{
struct Header header;
char data[128];
}; |
Je sérialise cette structure avec ces fonctions
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
|
unsigned char *Serialization::serialize_uint32(unsigned char *buffer, uint32_t arg)
{
buffer[3] = (arg >> 24);
buffer[2] = (arg >> 16);
buffer[1] = (arg >> 8);
buffer[0] = (arg);
return (buffer + sizeof(uint32_t));
}
unsigned char *Serialization::serialize_uint16(unsigned char *buffer, uint16_t arg)
{
buffer[1] = (arg >> 8);
buffer[0] = (arg);
return (buffer + sizeof(uint16_t));
}
unsigned char *Serialization::serialize_char(unsigned char *buffer, char arg)
{
buffer[0] = (arg);
return (buffer + sizeof(char));
}
unsigned char *Serialization::serialize_string(unsigned char *buffer, char *arg, int len)
{
int i;
i = -1;
while (++i < len)
buffer = serialize_char(buffer, arg[i]);
return (buffer);
}
unsigned char *Serialization::serialize_header(unsigned char *buffer, struct Header& arg)
{
buffer = serialize_uint32(buffer, arg.magic);
buffer = serialize_uint32(buffer, arg.checksum);
buffer = serialize_uint32(buffer, arg.timestamp);
buffer = serialize_uint16(buffer, arg.commandId);
buffer = serialize_uint16(buffer, arg.dataSize);
return (buffer);
}
unsigned char *Serialization::serialize_packet(unsigned char *buffer, struct Packet& arg)
{
buffer = serialize_header(buffer, arg.header);
buffer = serialize_string(buffer, arg.data, arg.header.dataSize);
return (buffer);
} |
je désérialise ainsi :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
unsigned char *Serialization::deserialize_uint32(unsigned char *buffer, uint32_t *arg)
{
memcpy((char*)arg, buffer, sizeof(uint32_t));
*arg = ntohl(*arg);
return (buffer + sizeof(uint32_t));
}
unsigned char *Serialization::deserialize_uint16(unsigned char *buffer, uint16_t *arg)
{
memcpy((char*)arg, buffer, sizeof(uint16_t));
return (buffer + sizeof(uint16_t));
}
unsigned char *Serialization::deserialize_char(unsigned char *buffer, char *arg)
{
memcpy(arg, buffer, sizeof(char));
return (buffer + sizeof(char));
}
unsigned char *Serialization::deserialize_string(unsigned char *buffer, char *arg, int len)
{
memcpy(arg, buffer, len);
return (buffer + len);
}
unsigned char *Serialization::deserialize_header(unsigned char *buffer, struct Header& arg)
{
buffer = deserialize_uint32(buffer, &arg.magic);
buffer = deserialize_uint32(buffer, &arg.checksum);
buffer = deserialize_uint32(buffer, &arg.timestamp);
buffer = deserialize_uint16(buffer, &arg.commandId);
buffer = deserialize_uint16(buffer, &arg.dataSize);
return (buffer);
}
unsigned char *Serialization::deserialize_packet(unsigned char *buffer, struct Packet& arg)
{
buffer = deserialize_header(buffer, arg.header);
buffer = deserialize_string(buffer, arg.data, arg.header.dataSize);
return (buffer);
} |
Le code d'envoi de mon client est :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
TcpSocket tcp;
Packet p;
char *serialized;
tcp.connectSocket("127.0.0.1", 4242);
p.header.magic = 0;
p.header.checksum = 1;
p.header.timestamp = 2;
p.header.commandId = 3;
p.header.dataSize = ss.str().length();
memset(p.data, 0, 128);
memcpy(p.data, "0", 2);
serialized = new char[sizeof(Header) + 2];
bzero(serialized, sizeof(Header) + 2);
Serialization::serialize_packet(serialized, p);
hexDump("serialized", serialized+1, sizeof(Header) + 2);
ret = tcp.write(serialized, sizeof(Header) + 3); |
et mon serveur recoit ainsi (cette fonction est appellé par la boucle sur le select()) :
Code:
1 2 3 4 5 6 7
|
int bav;
bav = socket->bytesAvailable();
buff = new char[bav];
socket->read(buff, bav);
hexdump("buff", buff, bav); |
methodes read et send de ma classe Socket :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
int TcpSocket::read(char *buff, int len)
{
int ret;
ret = recv(this->_socket, buff, len, 0);
return (ret);
}
int TcpSocket::bytesAvailable()
{
int ret;
char buff[65536];
ret = recv(this->_socket, buff, 65535, MSG_PEEK);
return (ret);
}
int TcpSocket::write(const std::string& buff, int len)
{
int ret;
ret = send(this->_socket, buff.c_str(), len, 0);
return (ret);
} |
voici les deux hexdumps :
client :
00 00 00 00 00 00 01 00 00 00 02 00 03 00 01 30 ...............0
server:
00 00 00 00 14 00 00 00 1c 00 00 00 1a 00 00 00 ...............
J'ai cherché pendant plusieurs jours avant de venir vous ennuyer avec mon problème.
En vous remerciant par avance