C/C++ [Résolu][C++][Full Socket] Thread, Parser, Reader

Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#21
Re: [C++][Full Socket] Threader la connexion

Gohu a dit:
Fais ton parseur avec Qt c'est beaucoup plus simple avec les QDataStream
Edit: je viens de me souvenir que si tu veux commencer tu as celui de Sorrow fait en c++ c'est celui que j'avais utilisé pour commencer
J'ai utilisé les QByteArray plutot que les QDataStream mais je pense que le principe de fonctionnement est le même.

Labo a dit:
Fais attention à comment tu reçois les paquets ! Soit tu fais comme dans les sources avec un buffer de 8192 Bytes, soit tu fais comme moi qui ne reçois que le header pour avoir la taille puis reçois exactement la taille du paquet.
Oui, j'ai fais en sorte de lire la taille du message et si le paquet reçu était de taille incohérente avec celle supposée alors j'ai lu le paquet suivant avant de traiter les données.

Sinon petite question de curiosité : lorsque je reçois un paquet de la part du serveur je reçois un message d'une taille supérieur à celle du paquet comme sur l'image ci-dessous où je reçois un message de taille 11 (11 bytes) alors qu'il en fait que 8. A quoi cela est-il dû ?

Cordialement,
Kangogoo.
 

Labo

Membre Actif
Inscrit
16 Aout 2013
Messages
799
Reactions
15
#22
Re: [C++][Full Socket] Threader la connexion

2 Octets pour les header + 1 pour la taille du message (vaut 8) + 8 fait bien 11.
8 est la taille du message (des data), et le paquet contient le header, la taille du message et le message.
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#23
Re: [C++][Full Socket] Threader la connexion

Bonsoir les amis.

J'ai actuellement terminé la lecture des paquet envoyés pour trouver l'id, la taille de la taille et la taille du message envoyé et j'aimerai savoir si selon vous cela semblait cohérent au niveau des résultats pour le premier paquet (id = 1) :

Ensuite je me suis attaqué au Reader des paquets et je voulais savoir si cela vous semblez correct dans l'ensemble ou si vous voyez quelques erreurs (j'espère pas trop) dans le code :
Code:
#include "DataReader.h"

DataReader::DataReader(QByteArray &_p)
{
  this->paquet = _p;
}

DataReader::DataReader()
{
}

QByteArray DataReader::getPaquet()
{
  return (this->paquet);
}

void DataReader::setPaquet(QByteArray &_p)
{
  this->paquet = _p;
}

int DataReader::getPos()
{
  return (this->pos);
}

void DataReader::setPos(int _pos)
{
  this->pos = _pos;
}

unsigned char DataReader::readNextByte()
{
  unsigned char myByte;
  myByte = this->paquet.at(this->pos);
  this->pos++;
  return (myByte);
}

QByteArray DataReader::readBytes(int _n)
{
  QByteArray myBytes;
  myBytes.resize(_n);
  for (int i = 0; i != _n; i++)
    myBytes.append(this->readNextByte());
  return (myBytes);
}

short DataReader::readShort()
{
  short myShort;
  myShort = (short)((this->readNextByte() << 8) + this->readNextByte());
  return (myShort);
}

unsigned short DataReader::readUnsignedShort()
{
  unsigned short myUnsignedShort;
  myUnsignedShort =  (unsigned short)((this->readNextByte() * 256) + (this->readNextByte()));
  return (myUnsignedShort);
}

int DataReader::readInt()
{
  int myInt;
  myInt = (int)(this->readNextByte() << 24);
  myInt += (int)(this->readNextByte() << 16);
  myInt += (int)(this->readNextByte() << 8);
  myInt += (int)(this->readNextByte());
  return (myInt);
}

unsigned int DataReader::readUnsignedInt()
{
  unsigned int myUnsignedInt;
  myUnsignedInt = (unsigned int)(this->readNextByte() << 24);
  myUnsignedInt += (unsigned int)(this->readNextByte() << 16);
  myUnsignedInt += (unsigned int)(this->readNextByte() << 8);
  myUnsignedInt += (unsigned int)(this->readNextByte());
  return (myUnsignedInt);
}

bool DataReader::readBool()
{
  if (this->readNextByte() == 01)
    return (true);
  return (false);
}

std::string DataReader::readString()
{
  QByteArray myString;
  myString = this->readBytes(this->readUnsignedShort());
  return (std::string(myString.constData(), myString.size()));
}

Je pourrais alors ensuite m'attaqué au Writer.

Cordialement,
Kangogoo.

Ps : un QByteArray est un tableau de byte.
 
Inscrit
23 Novembre 2013
Messages
26
Reactions
0
#24
Re: [C++][Full Socket] Threader la connexion

Ayant codé la partie socket, ce que Hugo disait avec les QDatastream, c'est que de cette manière tu peux écrire/lire dans des fichiers sans changer une grande partie du code (pour une classe reader/writer polyvalente) - bref rien de critique
 

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#25
Re: [C++][Full Socket] Threader la connexion

Salut , si le paquet est 00 05 08 AA BB CC DD EE FF 00 11
00 05 , on prend les 14 ers bits (id)=> 1 et les 2 derniers (nbre d'octet(s) de la taille) =>1
comme nbre d'octet(s) de la taille = 1 alors on relit 1 octet =>08 , la taille du message id 1 est de 8 octets

ca je pense que tu as compris , sinon regarde la signature de Labo , il explique ca tres bien


par contre pour le message en lui meme y'a rien a decoder les 8 octets du message ca sera : AA BB CC DD EE FF 00 11
message id 1 de taille 8 octets = AA BB CC DD EE FF 00 11


apres faut encore gerer les cas ou y'a plusieurs messages dans un paquets , c'est simple faut continuer a lire la ou on c'est arrété
et ce que beaucoup oubli : les cas ou un message est sur plusieurs paquet , en gros si y'a pas assez d'octets dans le paquet pour avoir le message complet , pour ca faut sauver les octets du message pas complet dans un buffer et ajouter a la suite le paquet qui va suivre
peu etre que tu le fais (ou pas , apperement c'est plutot "ou pas") j'ai pas envie de refechir , le c++ ca me donne des boutons
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#26
Re: [C++][Full Socket] Threader la connexion

Merci toons pour tes explications.
Donc il semblerait que les paquets ne soit pas correctement récupérer puisque il diffère du message reçu.
Sinon lorsque un même message est sur plusieurs paquets je l'ai intégré à mon parseur, mais je n'ai pas encore pu le tester.

Je vais revoir tout sa. Merci de votre aide

Cordialement,
Kangogoo

Edit : Problème résolu, je récupère maintenant bien les paquets.
Je peux donc passer au traitement des packets (reader/writer). Est ce que mon dataReader vous semble correct ou vous y voyez des erreurs/améliorations possibles (voir message précédent) ?
 

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#27
Re: [C++][Full Socket] Threader la connexion

manque les cas ou le paquet est trop petit pour un gros message mais ces cas la sont assez rares
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#28
Re: [C++][Full Socket] Threader la connexion

ToOnS a dit:
manque les cas ou le paquet est trop petit pour un gros message mais ces cas la sont assez rares
Tu parles pour le parseur ou pour le reader ?
Pck j'ai déjà tenu compte de sa dans mon parseur : si la taille récupérer + index + la taille de taille est plus grand que la taille du paquet alors je stocké sa dans un bytearray intermédiaire, je lis la suite, je concatene et je traite.
 

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#29
Re: [C++][Full Socket] Threader la connexion

ah ok alors ca roule
 

Labo

Membre Actif
Inscrit
16 Aout 2013
Messages
799
Reactions
15
#30
Re: [C++][Full Socket] Threader la connexion

ToOnS a dit:
ca je pense que tu as compris , sinon regarde la signature de Labo , il explique ca tres bien
Merciiiiiiiiiii :D

Si tu veux pas te faire chier avec les paquets bizarrement découpés, relis mon message :
Labo a dit:
Fais attention à comment tu reçois les paquets ! Soit tu fais comme dans les sources avec un buffer de 8192 Bytes, soit tu fais comme moi qui ne reçois que le header pour avoir la taille puis reçois exactement la taille du paquet.
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#31
Re: [C++][Full Socket] Threader la connexion

J'ai bien lu ton message Labo concernant la récupération du paquet mais j'ai préférer faire comme ça pour le moment. Après si je vois que cela ne marche pas (j'ai pas encore reçu de paquet de plus de 8192 octets) je pencherais certainement vers ta solution.

Cordialement,
Kangogoo.
 

Labo

Membre Actif
Inscrit
16 Aout 2013
Messages
799
Reactions
15
#32
Re: [C++][Full Socket] Threader la connexion

D'accord :)
Normalement, tu sauras si c'est nécessaire quand tu auras géré la connexion du personnage : c'est là qu'on reçoit plein de paquets d'un coup.
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#33
Re: [C++][Full Socket] Threader la connexion

Ok, merci de cette précision. Je le saurais donc assez vite.
Par contre au niveau de mon Reader, est ce qu'il vous semble correct, j'ai quelque doute :
Code:
#include "DataReader.h"

DataReader::DataReader(QByteArray &_p)
{
  this->paquet = _p;
}

DataReader::~DataReader()
{
}

QByteArray DataReader::getPaquet()
{
  return (this->paquet);
}

void DataReader::setPaquet(QByteArray &_p)
{
  this->paquet = _p;
}

int DataReader::getPos()
{
  return (this->pos);
}

void DataReader::setPos(int _pos)
{
  this->pos = _pos;
}

unsigned char DataReader::readNextByte()
{
  unsigned char myByte;
  myByte = this->paquet.at(this->pos);
  this->pos++;
  return (myByte);
}

QByteArray DataReader::readBytes(int _n)
{
  QByteArray myBytes;
  myBytes.resize(_n);
  for (int i = 0; i != _n; i++)
    myBytes.append(this->readNextByte());
  return (myBytes);
}

short DataReader::readShort()
{
  short myShort;
  myShort = (short)((this->readNextByte() << 8) + this->readNextByte());
  return (myShort);
}

unsigned short DataReader::readUnsignedShort()
{
  unsigned short myUnsignedShort;
  myUnsignedShort =  (unsigned short)((this->readNextByte() * 256) + (this->readNextByte()));
  return (myUnsignedShort);
}

int DataReader::readInt()
{
  int myInt;
  myInt = (int)(this->readNextByte() << 24);
  myInt += (int)(this->readNextByte() << 16);
  myInt += (int)(this->readNextByte() << 8);
  myInt += (int)(this->readNextByte());
  return (myInt);
}

unsigned int DataReader::readUnsignedInt()
{
  unsigned int myUnsignedInt;
  myUnsignedInt = (unsigned int)(this->readNextByte() << 24);
  myUnsignedInt += (unsigned int)(this->readNextByte() << 16);
  myUnsignedInt += (unsigned int)(this->readNextByte() << 8);
  myUnsignedInt += (unsigned int)(this->readNextByte());
  return (myUnsignedInt);
}

bool DataReader::readBool()
{
  if (this->readNextByte() == 01)
    return (true);
  return (false);
}

std::string DataReader::readString()
{
  QByteArray myString;
  myString = this->readBytes(this->readUnsignedShort());
  return (std::string(myString.constData(), myString.size()));
}
 

Labo

Membre Actif
Inscrit
16 Aout 2013
Messages
799
Reactions
15
#34
Re: [C++][Full Socket] Threader la connexion

Je comprends pas pourquoi parfois tu utilises des opérations left et parfois la multiplication (je sais d'ailleurs pas si ça fonctionne sur des QByte).
Sinon, je pense que tu lis bien le signe dans les short et int mais je comprends plus ce que veut dire (int) par exemple dans :
Code:
myInt = (int)(this->readNextByte() << 24);
C'est sûrement un convertisseur, j'ai oublié la syntaxe.
Après tout, la meilleure vérification, c'est le test. Comme a dit Knuth :
Donald a dit:
Faites attention aux bogues dans ce code ; je n'ai fait que démontrer qu'il était correct, je ne l'ai pas essayé.
Et c'est bien d'avoir pensé au big endian !

Ah et aussi, moi j'ai une fonction readUnsignedByte dans mon reader, on doit en avoir besoin quelque part.
 

Gohu

Membre Actif
Inscrit
16 Novembre 2013
Messages
222
Reactions
2
#35
Re: [C++][Full Socket] Threader la connexion

Labo a dit:
Ah et aussi, moi j'ai une fonction readUnsignedByte dans mon reader, on doit en avoir besoin quelque part.
Oui a la récéption des paquets, si le lenType est de 1, tu lis la lenght en UByte :)
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#36
Re: [C++][Full Socket] Threader la connexion

Labo a dit:
Je comprends pas pourquoi parfois tu utilises des opérations left et parfois la multiplication (je sais d'ailleurs pas si ça fonctionne sur des QByte).
Sinon, je pense que tu lis bien le signe dans les short et int mais je comprends plus ce que veut dire (int) par exemple dans :
Code:
myInt = (int)(this->readNextByte() << 24);
C'est sûrement un convertisseur, j'ai oublié la syntaxe.
Après tout, la meilleure vérification, c'est le test. Comme a dit Knuth :
Donald a dit:
Faites attention aux bogues dans ce code ; je n'ai fait que démontrer qu'il était correct, je ne l'ai pas essayé.
Et c'est bien d'avoir pensé au big endian !

Ah et aussi, moi j'ai une fonction readUnsignedByte dans mon reader, on doit en avoir besoin quelque part.
C'est vrai que je varie entre la multiplication et l'opération left et je ne saurais te dire pourquoi. C'est juste venu sur le moment. C'est vrai que je ne sais pas non plus si les opérateurs "<<" fonctionne avec les QByteArray, je vais vérifier de suite.
Le "(int)" c'est un cast explicite : c'est pour être sur d'avoir le bon type.
Ton readUnsignedByte est équivalent a mon readNextByte, il lit le prochain octet tout simplement.

Cordialement,
Kangogoo.

Edit : A priori, pas de soucis avec les opérateurs "<<" et ">>" pour les QByteArray. Je vais commencer à faire le Writer pour pouvoir tester au plus vite à la fois de reader et le writer et ainsi me rendre compte si il y a des bogue ou non.
 

Labo

Membre Actif
Inscrit
16 Aout 2013
Messages
799
Reactions
15
#37
Re: [C++][Full Socket] Threader la connexion

Moi, je pensais plutôt que le problème viendrait de la multiplication :p Mais après tout, le typage est faible en C/C++.
Ah oui, en effet, j'avais pas lu le type de retour de readNextByte, je croyais qu'il renvoyait un QByte, sauf que ça existe pas (enfin pas à ma connaissance) :)
Conclusion : ton reader était très bien, tu manques juste de confiance :D
 
Inscrit
27 Aout 2012
Messages
264
Reactions
0
#38
Re: [C++][Full Socket] Threader la connexion

Wut Labo ? Le typage est faible en C/C++ ?
Moi je trouve plutôt que le typage est fort dans ces langages.
C'est le PHP par exemple qui a un typage faible.
 

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#39
Re: [C++][Full Socket] Threader la connexion

 

Labo

Membre Actif
Inscrit
16 Aout 2013
Messages
799
Reactions
15
#40
Re: [C++][Full Socket] Threader la connexion

@alexandre : j'ai pas compris la fin avec Mac.
@Moonlight-Angel : tu peux additionner un short avec un long et le stocker dans un long (par exemple). En général, on s'en rend pas trop compte tellement ça paraît évident, mais quand tu fais du Caml, dont le typage est aussi statique mais fort, on voit la différence avec le C :p Genre on a des opérations pour les entiers (+, -, *, /) et des opérations pour les flottants (.+, .-, .*, ./) :lol:
@kangogoo : Essaye de changer le titre du sujet pour pas te faire allumer par Sparkdaemon, vu que tu es parti un peu loin de ta question initiale sur les threads.
 
Haut Bas