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

Linux Discussion :

Problème TCP non bloquant sous Linux (C++)


Sujet :

Linux

  1. #1
    Membre éclairé Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Points : 823
    Points
    823
    Par défaut Problème TCP non bloquant sous Linux (C++)
    Bonjour,

    Tout d'abord, j'espère poster au bon endroit... En tout voici mon problème:

    Une tâche maître (M) doit initier une communication avec d'autres tâches esclaves (E), situées sur d'autres ordinateurs (polling). Mais je ne sais pas si les programmes E tournent (peut-être que l'un des ordinateurs est même éteint!). Comme la taille des données est parfois importante ( > 1KB), je préfère utiliser TCP qu'UDP. Mais il ne faut pas qu'une connection défaillante bloque le polling! Donc j'ai choisi de travailler avec une connexion non-blocking TCP.

    La séquence que je fais pour l'init de connexion est la suivante:
    1) Création socket
    2) Flag non bloquant
    3) Connect
    4) Si connexion OK, envoi du message (sur la même machine c'est très rapide)
    5) Sinon démarrage tempo (gettimeofday())

    Puis, au second passage je fais:
    1) Test connexion (select() sur socket en read et write sans tempo)
    2) Si écriture possible, connexion OK!
    3) Sinon vérif tempo et éventuellement abandon

    Et ce qui ne fonctionne pas, c'est le test de connexion:
    Si le programme E ne tourne pas (celui qui reçoit la demande de connexion), j'ai quand même un retour positif (connexion OK)!

    Le code du test:
    Les fonctions w_* sont des wrappers pour récupérer automatiquement les erreurs système.
    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
     
    // test connection in progress
    do
    {
        retValue = w_select(daemonFd + 1, &readSet, &writeSet, 0, &timeStruct);
    } while (retValue == -1 && errno == EINTR);
    if (retValue == -1)
    {
        return;
    }
    // if connection is finally OK!
    if (FD_ISSET(daemonFd, &writeSet) != 0 && FD_ISSET(daemonFd, &readSet) == 0)
    {
        pMsgStruct = pMsg->getMsg(SERVER_REQUEST);
        if (w_write(daemonFd, pMsgStruct->pFullString, pMsgStruct->size) != -1)
        {
            pMsg->remMsg(SERVER_REQUEST);
            connectTimeStruct.tv_sec = 0;
            connectTimeStruct.tv_usec = 0;
        }
        return;
    }
    Ma question est:
    Comment puis-je tester que la connexion est bonne (dans mon code, c'est le if (FD_ISSET(...)) )? Merci d'avance pour vos réponses.

  2. #2
    Membre éclairé Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Points : 823
    Points
    823
    Par défaut
    À force de tourner autour du problème, je commence à avoir des éléments de réponse:

    1) Je fais un select( ) pour vérifier si le socket est writable.
    2) Je vérifie que j'ai reçu quelque chose sur ce canal.
    3) Je vérifie s'il y a eu une erreur et laquelle c'est.

    Ce qui donne pour la vérification:
    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
     
    // check daemon connection
    do
    {
        retValue = w_select(daemonFd + 1, &readSet, &writeSet, 0, &timeStruct);
    } while (retValue == -1 && errno == EINTR);
    if (retValue == -1)
    {
        return;
    }
    // if something on the daemon socket
    if (FD_ISSET(daemonFd, &writeSet) != 0)
    {
        int selectError;
        socklen_t len = sizeof(selectError);
        if (w_getsockopt(daemonFd, SOL_SOCKET, SO_ERROR, &selectError, &len) == -1)
        {
            return;
        }
        // if no error
        if (selectError == 0)
        {
            // connection OK, do something with the socket
            ...
             return;
        }
        // if connection not established yet
        ...
        // if connection refused
        ...
    }
    Je dois encore vérifier différents cas...

  3. #3
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Points : 17 923
    Points
    17 923
    Billets dans le blog
    2
    Par défaut
    je ne connais pas en C++,mais le principe (et le code) ne doit pas etre different du C.

    Pour passer en non-bloquant, c'est APRES la connexion, une fois le clone cree, et les id de sockets envoyes au client.

    La tu peux passer le socket en non bloquant...

  4. #4
    Membre éclairé Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Points : 823
    Points
    823
    Par défaut
    Bonjour,

    Je suis obligé d'utiliser le C++ à cause de l'utilisation d'une bibliothèque. Mais les appels système se font toujours en C.

    Ce qui est important pour moi, c'est qu'à aucun moment les programmes ne bloquent à cause de la com. Si je fais connect( ) pour un socket normal (bloquant) vers un programme inexistant, le programme s'arrête pendant plus d'une minute. Donc je dois modifier les options (setsockopt( )) dès que le socket est créé. Ensuite je n'en ai plus vraiment besoin de l'option non-bloquant (O_NONBLOCK) puisque je fais des read( ) seulement s'il y a quelque chose dessus...

    Je ne crée pas de threads supplémentaires: pour le polling je vais voir chaque programme esclave un par un, pour éviter les pics sur le réseau.

  5. #5
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Points : 17 923
    Points
    17 923
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par jmelyn Voir le message
    Je ne crée pas de threads supplémentaires: pour le polling je vais voir chaque programme esclave un par un, pour éviter les pics sur le réseau.
    Ah oui ? en faisant un boucle ???

    A ton avis ça sert à quoi les sockets non bloquants ??

Discussions similaires

  1. problème de fifo bloquant sous linux
    Par Fonzy007 dans le forum POSIX
    Réponses: 6
    Dernier message: 20/05/2009, 09h44
  2. Compenser wmode non implémenté sous linux
    Par Daisybodo dans le forum ActionScript 1 & ActionScript 2
    Réponses: 4
    Dernier message: 16/01/2008, 16h07
  3. Problème eclipse en français sous Linux
    Par Arthuris dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 04/05/2007, 15h41
  4. Problème de jardinage mémoire sous Linux
    Par Mike29 dans le forum C
    Réponses: 7
    Dernier message: 01/08/2006, 19h02
  5. [Installation] javac non trouvé sous linux
    Par melmouj dans le forum Général Java
    Réponses: 8
    Dernier message: 14/11/2005, 13h36

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