Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 3 sur 3
  1. #1
    Nouveau Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    décembre 2011
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : décembre 2011
    Messages : 43
    Points : 31
    Points
    31

    Par défaut [Boost Asio] Utilisation des tuples et organisation des classes

    Bonjour,

    Je lis le tutoriel suivant sur Boost Asio : http://gwenael-dunand.developpez.com...pp/boost/asio/ et j'essaye de comprendre le fonctionnement du serveur dans la partie 7.

    J'ai en fait deux questions.

    La première concerne l'utilisation des tuples. Dans les méthodes handle_read_header et handle_read_data de la classe tcp_connection on utilise l'instruction suivante :

    Code :
    boost::get<0>(handler)(e);
    J'ai compris l'intérêt d'utiliser les tuples, je sais que boost::get<0>(handler) nous permet d'accéder à l'élément 0 du tuple handler, mais pourquoi rajouter ce (e) à la suite ? Je ne trouve rien dans la doc de Boost Tuple.


    La deuxième question est plus générale. Je vois qu'il y a beaucoup de classes à créer pour la création du serveur et je voudrais savoir si cette manière d'organiser nos classes varie beaucoup selon les projets ?
    Si je crée une application réseau est ce que je pourrais me baser sur cette "organisation des classes" même s'il ne s'agit pas d'un chat ? Est ce que je pourrais chercher à obtenir une organisation similaire (plus ou moins bien sûr) ?

    J'attends vos réponses et conseils avec impatience

    Bonne journée !

  2. #2
    Membre Expert

    Inscrit en
    mai 2008
    Messages
    1 009
    Détails du profil
    Informations forums :
    Inscription : mai 2008
    Messages : 1 009
    Points : 2 199
    Points
    2 199

    Par défaut

    Bonjour,
    Citation Envoyé par SalutAVous Voir le message
    La première concerne l'utilisation des tuples. Dans les méthodes handle_read_header et handle_read_data de la classe tcp_connection on utilise l'instruction suivante :

    Code :
    boost::get<0>(handler)(e);
    [...] mais pourquoi rajouter ce (e) à la suite ?
    Ce qui a été mis dans le tuple comme premier élément est une callback prenant en argument un system::error_code.
    Donc ce que fait ce bout de code c'est extraire la callback du tuple et l’appeler aussitôt en passant e comme argument.
    (Par callback j'entends un objet appelable avec l’opérateur() comme un pointeur de fonction ou une fonction-objet)
    On aurait pu faire en deux temps :
    Code :
    1
    2
    3
     
    Handler& callback = boost::get<0>(handler);
    callback(e);
    Citation Envoyé par SalutAVous Voir le message
    J'ai compris l'intérêt d'utiliser les tuples
    Vraiment ? Car moi je ne comprends pas bien pourquoi l'auteur du tutoriel les a utilisé.
    Quel est l'intérêt de passer en argument des tuple d'un seul élément ? Pourquoi ne pas passer directement l'élément en question ?
    Il me semble qu'on pourrait utiliser directement un code comme celui-ci :
    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
     
       // Lecture asynchrone de données depuis le socket
       template <typename T, typename Handler>
       void async_read(T& t, Handler handler)
       {
       boost::asio::async_read(m_socket, boost::asio::buffer(m_inbound_header),
          boost::bind(&tcp_connection::handle_read_header<T, Handler>,
                          this, boost::asio::placeholders::error, boost::ref(t), handler));
       }	
     
       //Interprétation du header
       template <typename T, typename Handler>
       void handle_read_header(const boost::system::error_code& e, T& t, Handler handler)
       {
          if (e)
          {
             handler(e);
          }
          else
          {
             // Détermine la longueur du vrai message (11)
             std::istringstream is(std::string(m_inbound_header, header_length));
    	std::size_t m_inbound_datasize = 0;
    	if (!(is >> std::hex >> m_inbound_datasize))
    	{
    	   // Header non valide, on informe la fonction appelante
    	   boost::system::error_code error(boost::asio::error::invalid_argument);
               handler(error);
    	   return;
    	}
     
    	// On récupère les données (12)
    	m_inbound_data.resize(m_inbound_datasize);
     
    	boost::asio::async_read(m_socket, boost::asio::buffer(m_inbound_data),
               boost::bind(&tcp_connection::handle_read_data<T, Handler>, this,
    				boost::asio::placeholders::error, boost::ref(t), handler));
    	}
       }
     
       // Les données reçues, on les désérialise (13)
       template <typename T, typename Handler>
       void handle_read_data(const boost::system::error_code& e,
       T& t, Handler handler)
       {
          if (e)
          {
             handler(e);
          }
          else
          {
             // On extrait (14)
             try
    	 {
    	    std::string archive_data(&m_inbound_data[0], m_inbound_data.size());
    	    std::istringstream archive_stream(archive_data);
    	   boost::archive::text_iarchive archive(archive_stream);
    	   archive >> t;
    	  }
    	  catch (std::exception&)
    	  {
    	      // En cas d'échec
    	      boost::system::error_code error(boost::asio::error::invalid_argument);
    	     handler(error);
    	     return;
    	   }
     
    	// On informe l'appelant que tout s'est bien passé. (15)
    	handler(e);
    	}
       }
    Citation Envoyé par SalutAVous Voir le message
    La deuxième question est plus générale. Je vois qu'il y a beaucoup de classes à créer pour la création du serveur et je voudrais savoir si cette manière d'organiser nos classes varie beaucoup selon les projets ?
    Si je crée une application réseau est ce que je pourrais me baser sur cette "organisation des classes" même s'il ne s'agit pas d'un chat ? Est ce que je pourrais chercher à obtenir une organisation similaire (plus ou moins bien sûr) ?
    Là je ne sais pas trop, pas assez d'expérience sur les serveurs, faut voir ce qu'en pense les autres intervenants.

  3. #3
    Nouveau Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    décembre 2011
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : décembre 2011
    Messages : 43
    Points : 31
    Points
    31

    Par défaut

    Citation Envoyé par Arzar Voir le message
    Bonjour,


    Ce qui a été mis dans le tuple comme premier élément est une callback prenant en argument un system::error_code.
    Donc ce que fait ce bout de code c'est extraire la callback du tuple et l’appeler aussitôt en passant e comme argument.
    (Par callback j'entends un objet appelable avec l’opérateur() comme un pointeur de fonction ou une fonction-objet)
    On aurait pu faire en deux temps :
    Code :
    1
    2
    3
     
    Handler& callback = boost::get<0>(handler);
    callback(e);
    Super, je comprends maintenant

    Vraiment ? Car moi je ne comprends pas bien pourquoi l'auteur du tutoriel les a utilisé.
    Quel est l'intérêt de passer en argument des tuple d'un seul élément ? Pourquoi ne pas passer directement l'élément en question ?
    Il me semble qu'on pourrait utiliser directement un code comme celui-ci :
    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
     
       // Lecture asynchrone de données depuis le socket
       template <typename T, typename Handler>
       void async_read(T& t, Handler handler)
       {
       boost::asio::async_read(m_socket, boost::asio::buffer(m_inbound_header),
          boost::bind(&tcp_connection::handle_read_header<T, Handler>,
                          this, boost::asio::placeholders::error, boost::ref(t), handler));
       }	
     
       //Interprétation du header
       template <typename T, typename Handler>
       void handle_read_header(const boost::system::error_code& e, T& t, Handler handler)
       {
          if (e)
          {
             handler(e);
          }
          else
          {
             // Détermine la longueur du vrai message (11)
             std::istringstream is(std::string(m_inbound_header, header_length));
    	std::size_t m_inbound_datasize = 0;
    	if (!(is >> std::hex >> m_inbound_datasize))
    	{
    	   // Header non valide, on informe la fonction appelante
    	   boost::system::error_code error(boost::asio::error::invalid_argument);
               handler(error);
    	   return;
    	}
     
    	// On récupère les données (12)
    	m_inbound_data.resize(m_inbound_datasize);
     
    	boost::asio::async_read(m_socket, boost::asio::buffer(m_inbound_data),
               boost::bind(&tcp_connection::handle_read_data<T, Handler>, this,
    				boost::asio::placeholders::error, boost::ref(t), handler));
    	}
       }
     
       // Les données reçues, on les désérialise (13)
       template <typename T, typename Handler>
       void handle_read_data(const boost::system::error_code& e,
       T& t, Handler handler)
       {
          if (e)
          {
             handler(e);
          }
          else
          {
             // On extrait (14)
             try
    	 {
    	    std::string archive_data(&m_inbound_data[0], m_inbound_data.size());
    	    std::istringstream archive_stream(archive_data);
    	   boost::archive::text_iarchive archive(archive_stream);
    	   archive >> t;
    	  }
    	  catch (std::exception&)
    	  {
    	      // En cas d'échec
    	      boost::system::error_code error(boost::asio::error::invalid_argument);
    	     handler(error);
    	     return;
    	   }
     
    	// On informe l'appelant que tout s'est bien passé. (15)
    	handler(e);
    	}
       }
    D'après ce que j'ai compris (mais peut être que je n'ai pas compris aussi) la fonction boost::bind() ne peut pas utiliser une fonction qui a été passée en paramètre à une fonction template dans laquelle elle est utilisée.

    Or le handler est passé en paramètre à la fonction template handle_read_header. Et dans cette fonction template handle_read_header on utilise la fonction boost::bind(), qui ne peut donc pas utiliser la fonction handler qui a été passée en paramètre à handle_read_header.

    Dans le tuto il est dit :
    Le code est relativement long, surtout à cause du fait que boost::bind ne supporte pas l'appel récursif lorsqu'il est templaté. C'est-à-dire que boost::bind ne peut pas (pour l'instant sans doute) binder une fonction passée via un template où boost::bind est utilisé.
    Du coup, on est obligé de passer par des tuple, qui n'ont normalement rien à voir là dedans. Je les ai gardés pour avoir un code qui compile. Faites en abstraction et gardez à l'esprit que le tuple en question est juste le callback.
    Après je n'ai pas cherché à vérifier si cela marchait sans utiliser de tuples, et peut être que j'ai simplement mal compris l'intérêt d'utiliser les tuples.



    En tout cas merci pour cette réponse, et j'en attends d'autres, concernant ma deuxième question.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •