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

Boost C++ Discussion :

[ASIO] Problème de socket


Sujet :

Boost C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2011
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Avril 2011
    Messages : 66
    Par défaut [ASIO] Problème de socket
    Bonjour à tous,

    je développe une application orientée P2P, et j'essaye de créer des noeuds à l'aide de boost ASIO. Je travaille sur une machine virtuelle VMWare (CentOS 5) sur laquelle j'ai déclaré 3 interfaces réseau comme suit:
    eth0: 192.168.0.10
    eth1: 192.168.0.11
    eth2: 192.168.0.12

    Je lance ensuite 3 fois mon application, chacune écoutant sur une interface différente (donné par argument)

    Jusque là, tout fonctionne bien, quand je fais un netstat après le lancement de mes 3 applis, j'ai bien mes 3 interfaces en LISTEN sur le port souhaité:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    tcp        0      0 192.168.0.12:7171           *:*                         LISTEN      
    tcp        0      0 192.168.0.11:7171           *:*                         LISTEN 
    tcp        0      0 192.168.0.10:7171           *:*                         LISTEN
    Je lance ensuite une recherche à partir de la première instance du programme (celui qui écoute en .0.10), pour qu'il essaye de se connecter au 2 autres via leur port d'écoute. La connexion (asynchrone) réussit, mais quand je regarde le socket de la connexion, j'obtiens ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    tcp        0      0 192.168.0.11:39890          192.168.0.11:7171           ESTABLISHED 
    tcp        0      0 192.168.0.11:7171           192.168.0.11:39890          ESTABLISHED 
    tcp        0      0 192.168.0.12:7171           192.168.0.12:47724          ESTABLISHED 
    tcp        0      0 192.168.0.12:47724          192.168.0.12:7171           ESTABLISHED
    Je n'ai donc pas de lien 10/11 et 10/12, mais à la place 11/11 et 12/12...
    Voici le code que j'utilise pour la connection:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void nvsnode::connect(tcp::endpoint& endpoint)
    {
        connec* new_node= new connec(m_io_serv);
        new_node->getSocket().async_connect(endpoint,
                                            boost::bind(&nvsnode::handle_connect, this,
                                                    new_node,
                                                    boost::asio::placeholders::error)
                                           );
    }
    D'ou peut provenir le problème,
    de la configuration de mes interfaces via VMWare?
    de mon code?
    d'une option pour spécifier l'interface de connection dans asio?
    un paramètrage spécial de CentOS?

    Merci de votre attention.

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 35
    Par défaut
    Bonjour Raz-X,

    Lorsque tu dis :
    Citation Envoyé par Raz-X Voir le message
    Je lance ensuite une recherche à partir de la première instance du programme (celui qui écoute en .0.10), pour qu'il essaye de se connecter au 2 autres via leur port d'écoute. La connexion (asynchrone) réussit, mais quand je regarde le socket de la connexion, j'obtiens ceci :
    Comment lances tu cette recherche ? Tu envoies une commande à ta première instance ? Tu utilises une autre application ? Car dans le code que tu as posté on ne voit pas la manière dont tu appelles ta fonction permettant de te connecter aux deux autres instances, je pense qu'il nous faudrait un petit peu plus de code afin de pouvoir t'aider à résoudre ton problème car on ne voit pas les arguments que tu passes à ta fonction.

    Cordialement
    Matarc

  3. #3
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2011
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Avril 2011
    Messages : 66
    Par défaut
    C'est assez simple.
    Au lancement de mon appli, je déclare un io_service, et je démarre un thread spécial pour les échanges réseaux de mon noeud (via un io_service.run())

    Le noeud connaît son interface sur laquelle il doit écouter (donnée en paramètre au lancement de l'appli) ainsi que le port par défaut (ici 7171). Je possède aussi une classe connec, qui représente chacune des connexions que je possède avec les autres noeuds.

    La classe connec possède simplement un tcp::socket (pour le moment) qui est passé en paramètre lors de tentatives de connexion du noeud vers les autres.

    J'initialise mon noeud comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    nvsnode::nvsnode(boost::asio::io_service& io_service,std::string ip,int port)
        :m_io_serv(io_service),
    //interface+port d'acoute
         m_listening_endpoint(boost::asio::ip::address::from_string(ip), port),
    //l'acceptor qui s'y connecte
         m_acceptorV4(io_service,m_listening_endpoint)
    {
    }
    par la suite, je lance une méthode startNode, qui elle même démarre tout d'abord l'écoute sur l'interface spécifiée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void nvsnode::startAcceptNodes()
    {
        connec* new_node= new connec(m_io_serv);
        m_acceptorV4.async_accept(new_node->getSocket(),
                                  boost::bind(&nvsnode::handle_accept,
                                              this,
                                              new_node,
                                              boost::asio::placeholders::error));
        std::cout<<"Start listening new nodes on "<< m_acceptorV4.local_endpoint()<<std::endl;
    }
    Puis quand cela est terminé, tente de se connecter aux 2 autres noeuds via cette méthode:
    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    void nvsnode::connectSuperNodes()
    {
        // On récupère la liste des SuperNodes pour s'y connecter
        boost::asio::ip::tcp::resolver resolver(m_io_serv);
        boost::asio::ip::tcp::resolver::query query("nodes.appli.local", "7171");
        boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query);
        boost::asio::ip::tcp::resolver::iterator end
     
        while (iter != end) // Pour chaque SuperNode
        {
            boost::asio::ip::tcp::endpoint endpoint = *iter++;
            if(endpoint.address().to_string().compare(m_listening_endpoint.address().to_string())!=0)
            {
                std::cout <<"Connexion au SuperNode "<< endpoint << std::endl;
                try{
                    connect(endpoint);
                }catch(const std::exception & e){
                    std::cout<<"ERREUR: "<< e.what() <<std::endl;
                }
            }
        }
    }
     
    void nvsnode::connect(tcp::endpoint& endpoint)
    {
        connec* new_node= new connec(m_io_serv);
        new_node->getSocket().async_connect(endpoint,
                                            boost::bind(&nvsnode::handle_connect, this,
                                                    new_node,
                                                    endpoint.address().to_string(),
                                                    boost::asio::placeholders::error)
                                           );
        std::cout<<"Connexion à: "<<endpoint<<" avec socket: "<<new_node->getSocket().local_endpoint()<<std::endl;
    }
    Voilà, vous savez tout ^^
    PS: Ce n'est pas très propre ni très évolué, j'essaye pour le moment de comprendre le pourquoi du comment. Je suis allé demander sur l'IRC de boost, et selon eux, cela vient plutôt du fait que j'utilise 3 interfaces sur la même machine, au lieux de 3 machines avec 1 interface chacune...

    Je vais tester ça en attendant, et voir si le problème persiste.
    Si vous avez des suggestions n'hésitez pas.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 35
    Par défaut
    Bonjour,

    Je ne pense pas que ça vienne de là mais sait-on jamais, pourrais tu nous montrer le contenu du fichier /etc/hosts ? La classe query va apparement chercher les noms d'host dans ce fichier.

    Cordialement
    Matarc

  5. #5
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2011
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Avril 2011
    Messages : 66
    Par défaut
    Voici le contenu de /etc/hosts
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    # Do not remove the following line, or various programs
    # that require network functionality will fail.
    127.0.0.1		localhost.localdomain localhost
    ::1		localhost6.localdomain6 localhost6

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 35
    Par défaut
    Citation Envoyé par Raz-X Voir le message
    Voici le contenu de /etc/hosts
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    # Do not remove the following line, or various programs
    # that require network functionality will fail.
    127.0.0.1		localhost.localdomain localhost
    ::1		localhost6.localdomain6 localhost6
    Euh quelque chose m'intrigue là pourrais tu vérifier que tu rentres bien dans la boucle dans la fonction ci-dessous, en affichant un message à l'écran par exemple ?

    Citation Envoyé par Raz-X Voir le message
    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    void nvsnode::connectSuperNodes()
    {
        // On récupère la liste des SuperNodes pour s'y connecter
        boost::asio::ip::tcp::resolver resolver(m_io_serv);
        boost::asio::ip::tcp::resolver::query query("nodes.appli.local", "7171");
        boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query);
        boost::asio::ip::tcp::resolver::iterator end
     
        while (iter != end) // Pour chaque SuperNode
        {
            boost::asio::ip::tcp::endpoint endpoint = *iter++;
            if(endpoint.address().to_string().compare(m_listening_endpoint.address().to_string())!=0)
            {
                std::cout <<"Connexion au SuperNode "<< endpoint << std::endl;
                try{
                    connect(endpoint);
                }catch(const std::exception & e){
                    std::cout<<"ERREUR: "<< e.what() <<std::endl;
                }
            }
        }
    }
     
    void nvsnode::connect(tcp::endpoint& endpoint)
    {
        connec* new_node= new connec(m_io_serv);
        new_node->getSocket().async_connect(endpoint,
                                            boost::bind(&nvsnode::handle_connect, this,
                                                    new_node,
                                                    endpoint.address().to_string(),
                                                    boost::asio::placeholders::error)
                                           );
        std::cout<<"Connexion à: "<<endpoint<<" avec socket: "<<new_node->getSocket().local_endpoint()<<std::endl;
    }

  7. #7
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2011
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Avril 2011
    Messages : 66
    Par défaut
    Je viens de tester, cela fonctionne, je rentre correctement dans la boucle, et je fais bien 2 connec (1 pour 0.11, et l'autre pour 0.12)

    La zone DNS que j'ai déclaré contient uniquement mes 3 interfaces en 10 11 et 12. Globalement tout fonctionne correctement, mais c'est l'attribution des sockets qui est très étrange.

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 35
    Par défaut
    Petite question bête, tu as bien pensé à appeler la méthode run() de ton io_service après l'attente de connexion et la tentative de connexion ?

Discussions similaires

  1. Asio : problèmes de socket fermé
    Par Kernald dans le forum Boost
    Réponses: 3
    Dernier message: 15/01/2009, 22h42
  2. Problême de Socket avec un applet java (RMI/policy)
    Par Vesperal dans le forum API standards et tierces
    Réponses: 3
    Dernier message: 12/04/2006, 12h00
  3. Réponses: 2
    Dernier message: 26/03/2004, 09h15
  4. [Kylix] Problème de socket
    Par RaygKross dans le forum EDI
    Réponses: 1
    Dernier message: 01/03/2004, 19h41
  5. Mysql ne se lance pas problème de socket
    Par Riko dans le forum Installation
    Réponses: 5
    Dernier message: 05/02/2004, 09h28

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