C/C++ [C++][Socket] writeShort / writeInt.

Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#1
Bonsoir,
Je travaille actuellement sur le writer de mon bot et je me demandais comment correctement écrire un short / unsigned short et un int.
Mon writer contient une list de char que je remplie à chaque write ce qui donne pour le moment :
Code:
D2Writer::D2Writer()
{
  this->byteList = new std::list<char>();
}

D2Writer::~D2Writer()
{
}

void D2Writer::writeByte(int v)
{
  this->byteList.push_back((char)(v));
}
Pour le cas d'un char/byte c'est assez simple mais pour le cas d'un short/unsigned short ou d'un int cela devient un peu plus complexe.
De ce que j'ai compris il faudrait convertir la valeur du nombre (contenue dans un int par exemple) en une chaîne de caractère (un string par exemple) pour ensuite écrire chaque caractère de cette chaîne à la suite de la liste. Mais je ne suis pas sur de cela.
Pouvez-vous m'éclairer sur ce point ?

Cordialement,
Kangogoo.
 
Inscrit
1 Mars 2014
Messages
120
Reactions
0
#2
Salut,

Pourquoi tu utilise une list de char ? Pourquoi ne pas utiliser directement un char[] ?
Ensuite dans ta fonction writeByte() tu passe un int en paramètre, tu devrai passer un char (vu que c'est un byte) et pour writeUByte tu passe un unsigned char.
Pour écrire un int ben faut découper le int en 4 bytes avec les opérateurs binaires et mettre chaque partis dans une case de ton tableau.
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#3
Pourquoi une list de char et pas un char[] tout simplement parce que je ne connais pas la taille de mon tableau. Une liste me permet de ne pas m'en soucier. Avec un char[] je devrait sans arrêt allouer/réallouer sa place en mémoire quand on fait plusieurs write() de suite.
C'est vrai que je devrais en effet passer un char et non un int mais j'ai regarder le tuto de Raphy (dans la section C#) et j'ai vu qu'il ne passer que des int en paramètre donc je me suis dis que cela ne devait pas avoir une grande importance.
Pour écrire un short ou un int il faut utiliser les opérateurs binaires mais c'est justement sur ce point que j'ai un peu de mal. Pourrais-tu étayer ton explication en me montrant un exemple pour le writeShort() par exemple ainsi je pourrais essayer de faire le writeInt() pour voir si j'ai bien compris.

Edit : Après quelque recherche j'en suis arrivé a ce résultat mais je n'en suis pas sur :
Code:
void writeShort(short s)
{
this->byteList.push_back((char)((s >> 8) & 0xFF));
this->byteList.push_back((char)(s & 0xFF));
}
Qu'en dites-vous ?

Cordialement,
Kangogoo.
 

Labo

Membre Actif
Inscrit
16 Aout 2013
Messages
799
Reactions
15
#4
Je vois pas l'intérêt d'une liste sur un vector par contre... (vu que tu rajoutes à la fin)
Il me semble qu'on peut convertir en big endian assez facilement avec des static_cast...
Et aussi qu'on est pas obligé de mettre le & 0xFF ni le char. En effet, la liste est déclarée comme liste de char d'où conversion implicite.
Et pourquoi char et pas unsigned char ?
 
Inscrit
1 Mars 2014
Messages
120
Reactions
0
#5
T'es pas obligé de ré-allouer à chaque fois ton tableau vu que tu sais qu'un paquet ca fait max 8192 octets (je crois bien, à confirmer). Je posterai un exemple plus tard, quand j'aurai boot sous linux !
 

BlueDream

Administrateur
Membre du personnel
Inscrit
8 Decembre 2012
Messages
2 010
Reactions
149
#6
Affirmaif 8192. Aucun paquet n est plus grand.
 

Gohu

Membre Actif
Inscrit
16 Novembre 2013
Messages
222
Reactions
2
#7
Je crois bien que si... Le raw fait actuellement 12000 bytes
 
Inscrit
27 Aout 2012
Messages
264
Reactions
0
#8
Mais il n'est pas envoyé en une fois. C'est un paquet splitté.
Si j'ai bien suivi, on parle ici de la taille maximum d'un paquet réseau non ?
 
Inscrit
1 Mars 2014
Messages
120
Reactions
0
#9
Oui, il utilise actuellement une std::list de char pour stocker son packet, ce qui lui évite de redimensionner son tableau à chaque ajout de donné. Mais je lui ai dit de faire un char tab[8192] vu qu'aucun paquet n'est plus grand.
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#10
DeepSiderZ a dit:
Oui, il utilise actuellement une std::list de char pour stocker son packet, ce qui lui évite de redimensionner son tableau à chaque ajout de donné. Mais je lui ai dit de faire un char tab[8192] vu qu'aucun paquet n'est plus grand.
Aucun paquet n'a de taille supérieur a 8192 mais tout les paquets ne font pas non plus cette taille. Lorsqu'un paquet fait moins de 8192 octets il est préférable d'utiliser une liste ou un vecteur niveau optimisation de la mémoire. D'autant plus qu'une liste ou un vecteur est un objet il est donc automatiquement détruit lorsqu'il n'est plus utiliser contrairement a un char * allouer avec new et qu'il faut delete.
C'est juste une question d'optimisation en réalité.

Sinon j'ai avancé sur le writter. Je suis passer sur un vecteur plutôt qu'une liste pour plus de simplicité dans le déplacement (pour la fonction pack()).
Je pense avoir codé toutes les fonctions nécessaire/utiles mais je ne suis pas sur de toute les avoir.
Que pensez-vous du writter ? Voyez-vous des améliorations possible ou des erreurs dans le code ?
Code:
#include "D2Writer.h"

D2Writer::D2Writer()
{
  this->byteList.clear();
}

D2Writer::~D2Writer()
{
}

int D2Writer::getTailleType()
{
  if (this->byteList.size() > 65535)
    return (3);
  if (this->byteList.size() > 255)
    return (2);
  if (this->byteList.size() > 0)
    return (1);
  return (0);
}

short D2Writer::getHeader(int id)
{
  return ((short)((id << 2) | this->getTailleType()));
}

void D2Writer::writeByte(char v)
{
  this->byteList.push_back((char)(v));
}

void D2Writer::writeShort(short s)
{
  this->byteList.push_back((char)(s >> 8));
  this->byteList.push_back((char)(s));
}

void D2Writer::writeUShort(unsigned short s)
{
  this->byteList.push_back((char)(s >> 8));
  this->byteList.push_back((char)(s));
}

void D2Writer::writeInt(int s)
{
  this->byteList.push_back((char)(s >> 24));
  this->byteList.push_back((char)(s >> 16));
  this->byteList.push_back((char)(s >> 8));
  this->byteList.push_back((char)(s));
}

void D2Writer::writeUInt(unsigned int s)
{
  this->byteList.push_back((char)(s >> 24));
  this->byteList.push_back((char)(s >> 16));
  this->byteList.push_back((char)(s >> 8));
  this->byteList.push_back((char)(s));
}

void D2Writer::writeString(std::string &str)
{
  for (std::string::iterator it = str.begin(); it != str.end(); ++it)
    this->byteList.push_back((char)((*it)));
}

void D2Writer::writeBool(bool b)
{
  if (b)
    this->byteList.push_back(1);
  else
    this->byteList.push_back(0);
}

char *D2Writer::packByte(int id)
{
  int i = 0;
  int taille = this->byteList.size();
  int tailleType = this->getTailleType();
  short h = this->getHeader(id);

  char *paquet = new char[2 + tailleType + taille];
  paquet[0] = (char)(h >> 8);
  paquet[1] = (char)(h - 256 * paquet[0]);

  switch(tailleType)
    {
    case 1:
      paquet[2] = (char)(tailleType);
      i = 3;
      break;
    case 2:
      paquet[2] = (char)(tailleType >> 8);
      paquet[3] = (char)(tailleType - 256 * paquet[2]);
      i = 4;
      break;
    case 3:
      paquet[2] = (char)(tailleType >> 16);
      paquet[3] = (char)(tailleType >> 8);
      paquet[4] = (char)(tailleType - 256 * paquet[3] - 256 * paquet[2]);
      i = 5;
      break;
    }
  for (int j = i; j < i + tailleType; j++)
    paquet[j] = this->byteList.at(j - i);

  return (paquet);
}
Merci d'avance.

Cordialement,
Kangogoo.
 
Inscrit
5 Decembre 2010
Messages
114
Reactions
0
#11
Petit up ?
Je ne sais plus si c'est autorisé ou non de "up" un sujet.
 

Labo

Membre Actif
Inscrit
16 Aout 2013
Messages
799
Reactions
15
#12
Ben à ma connaissance, il y a pas de règle, mais un UP justifié est toléré, par exemple quand on a posé une question et qu'on est en droit de penser que le message a disparu des nouveaux messages à cause d'un mauvais timing (raison de plus de faire un autre forum).

Que pensez-vous du writter ? Voyez-vous des améliorations possible ou des erreurs dans le code ?
Si personne n'a répondu, c'est que personne n'a vu d'améliorations possibles ou d'erreur dans le code :D

Franchement, perds pas ton temps là-dessus, il y a des choses plus dures :mrgreen:
 

Shornaal

Membre Actif
Inscrit
17 Février 2011
Messages
194
Reactions
0
#13
Je ne développe plus de bot Dofus et pour être franc le bitwise est loin d'être mon fort mais à mon sens le meilleur moyen de savoir si ton writer est exact est simplement de le tester et de comparer les données que tu écris avec par rapport à ce que tu sniffes avec des actions analogues. Tu seras rapidement fixé ! Une autre solution si tu es certain que ton reader fonctionne est de lire ce que tu packs avec ton writer, tu verras bien si les valeurs sont les bonnes. Courage ! :D
 
Haut Bas