IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

Ecrire un double sur une socket


Sujet :

Réseau C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2014
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2014
    Messages : 14
    Par défaut Ecrire un double sur une socket
    Salut,

    j'suis actuellement sur un projet de client/serveur en C/C++ et je dois donc communiquer des informations entre mon serveur et mon client.

    Pour se faire je n'ai pas voulu envoyer des commandes textes au serveur car je trouve pas ça très agréable à manipuler. Je préfère directement inscrire les données comme elles sont. Je tiens à préciser que j'écrit ces données en big endian.
    Pour faire ça j'ai donc fait deux classe, DataInput et DataOutput. Leur structure est assez simple, j'ai pour chaque type une méthode qui écrit dans un buffer la donnée, et une méthode qui lit cette donnée depuis le buffer.
    Par exemple :

    pour écrire un int :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void                                    DataOutput::writeInt(int i)
    {
      _buf += (i >> 24);
      _buf += (i >> 16) & 0xff;
      _buf += (i >> 8) & 0xff;
      _buf += i & 0xff;
    }
    pour lire un int :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    int                             DataInput::readInt()
    {
      int                           ret;
     
      ret = _buf[_pos] << 24;
      ret |= ((_buf[_pos + 1] & 0xff) << 16);
      ret |= ((_buf[_pos + 2] & 0xff) << 8);
      ret |= _buf[_pos + 3] & 0xff;
      _pos += 4;
      return (ret);
    }
    Tout ça fonctionne à merveille et je pense d'ailleurs que c'est un procédé classique.
    Mais je me heurte à un problème. Je ne sais pas comment écrire un double ou encore un float. Est ce que vous auriez une idée de comment faire ceci ?
    Merci beaucoup !

  2. #2
    Membre chevronné
    Inscrit en
    Décembre 2010
    Messages
    290
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 290
    Par défaut
    En effet les opérateurs bit à bit ne fonctionnent pas sur les types float & double, du coup écrire une fonction de swap c'est pas forcément le plus simple.
    Y a longtemps, dans le source de Quake (https://github.com/id-Software/Quake...Quake/common.c), j'étais tombé là dessus :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    float FloatSwap (float f)
    {
    	union
    	{
    		float   f;
    		byte    b[4];
    	} dat1, dat2;
     
     
    	dat1.f = f;
    	dat2.b[0] = dat1.b[3];
    	dat2.b[1] = dat1.b[2];
    	dat2.b[2] = dat1.b[1];
    	dat2.b[3] = dat1.b[0];
    	return dat2.f;
    }
    Tu dois pouvoir adapter ce code pour les doubles sans trop de problèmes, mais je n'ai jamais essayé.

    Un peu hors-sujet, le même code contient une petite perle pour détecter de façon portable si la machine sur laquelle le code s'exécute fonctionne en big-endian ou en little-endian:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    	byte    swaptest[2] = {1,0};
     
    // set the byte swapping variables in a portable manner 
    	if ( *(short *)swaptest == 1)
    	{
    		bigendien = false;
    	}
    	else
    	{
    		bigendien = true;
    	}

  3. #3
    Membre émérite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Par défaut
    Je suppose que _buf est un char* ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    // Ecriture
    double d = /* ... */;
    *(double*)_buf = d;
    Mais ça ne fonctionnera bien sûr que si les deux machines ont la même endianness et la même implémentation de double.

    Au passage, je ne comprends pas le premier extrait de code que tu postes ... Le _buf déclaré est le même que dans le deuxième extrait ? Pourquoi "+=" ?

  4. #4
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2014
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2014
    Messages : 14
    Par défaut
    Oui j'ai pas été super clair sur mes bouts de code.

    Dans le premier, qui correspond à DataOutput, _buf est une string c'est pour ça que je peux faire += (et sur ma socket j'écrit _buf.c_str()). Manipuler une string est plus simple qu'un char * c'est pour ça que j'fais ça.
    Dans le second c'est bien un char *, celui que je reçoit du serveur du coup !

    Je vais essayer vos propositions, je reviens pour vous dire ce qu'il en est.

    Merci en tous cas !

  5. #5
    Membre émérite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Par défaut
    D'accord. Je précise que le code que je t'ai fourni comme exemple considère que _buf est un char*

  6. #6
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2014
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2014
    Messages : 14
    Par défaut
    Je viens de faire le test qui n'est pas concluant, mais peut être que j'my prend mal ? Voici ce que j'ai fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    void                                    DataOutput::writeDouble(double d)
    {
      // A la base je manipule une string donc je doit la repasser en char* avec ces deux lignes
      char                                  *buftmp = new char [_buf.length() + 1];
      std::strcpy(buftmp, _buf.c_str());
     
      // j'applique la méthode de the Hund
      *(double *)buftmp = d;
     
      // je remet mon char* dans ma string.
      _buf = buftmp;
    }
    Je me fait un petit main de test :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    int main()
    {
      DataOutput o;
     
      // j'écrit une chaine en 1er pour ensuite essayer de la lire
      o.writeUTF("salut");
      // j'écrit mon double
      o.writeDouble(3.14);
     
      // je passe mon buffer à ma classe input
      DataInput     in(o.getBuf());
     
      // j'essaye de lire la chaine
      std::cout << in.readUTF() << std::endl;
    }
    La sortie attendu est "salut" mais j'obtient que des caractères bizzares . Est ce que c'est parce que j'utilise une string à la base, que je transforme en char* puis repasse en string ?
    Sinon pour la lecture comment vais-je devoir faire ? Mon systeme actuel me permet d'appeler mes fonctions de read et grâce à une variable dans ma classe je sauvegarde ma position ce qui fait que plus j'appelle de méthode pour lire et plus j'avance dans mon char*.

    Merci !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Ecrire du binaire sur une Socket
    Par _LittleFlea_ dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 04/03/2011, 11h39
  2. Ecrire du texte sur une fenêtre de Jeu vidéo (OSD)
    Par zenway dans le forum DirectX
    Réponses: 7
    Dernier message: 07/03/2009, 14h06
  3. Ecrire du texte sur une Overlay Surface
    Par deakuk dans le forum DirectX
    Réponses: 1
    Dernier message: 17/02/2006, 13h52
  4. [visual c++] connaitre le debit sur une socket
    Par khayyam90 dans le forum MFC
    Réponses: 4
    Dernier message: 25/10/2005, 16h12
  5. [VMR9][D3D9]ecrire un texte sur une surface
    Par drizztfr dans le forum DirectX
    Réponses: 2
    Dernier message: 13/11/2003, 15h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo