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 :

Pb de socket : select() et send()


Sujet :

Réseau C

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut Pb de socket : select() et send()
    Bonjour,

    comment tester avant de faire un send() que la socket est valide ?
    si j'utilise la fonction select(), elle me renvoie toujours que la socket placée dans le FD_SET est valide, puisqu'elle me renvoie toujours 1.

    Une idée ?

    @+

  2. #2
    Expert confirmé
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 4 062
    Points
    4 062
    Par défaut
    On peut faire des tests a chaque etape de la creation du socket.

    Sinon un test au niveau de "connect" pour un socket "client"
    ou au niveau de "bind" pour un socket "serveur".

    Ces étapes précédants logiquement l'envoi de données.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut
    non, pas si tu fais une connexion permanente.

    Dans une connexion permanente, tu te connectes avec la fonction connect(), qui te renvoie ton descripteur (ta socket).
    Puis tu peux faire des send() ou des recv() sur cette socket.

    Or avant de faire un send(), j'aimerais savoir si mon serveur n'est pas tombé.
    Donc je teste avec select(), mais ça ne marche pas !!

    @+

  4. #4
    Membre averti Avatar de niglo
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    379
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 379
    Points : 383
    Points
    383
    Par défaut
    Tu peux essayer de faire un send de "test" avant ton vrai send pour savoir si la connesxion est toujours OK ! Sinon, tu peux essayer de pinger le serveur mais si il répond ca voudra pas dire que ta socket est toujours OK. Je pense qu'un send "test" est une bonne solution en testant sa valeur de retour !

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut
    non, car un send() marche toujours même sur une socket() "bidon"

  6. #6
    Membre averti Avatar de niglo
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    379
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 379
    Points : 383
    Points
    383
    Par défaut
    Citation Envoyé par olive_le_malin
    non, car un send() marche toujours même sur une socket() "bidon"
    tu es sur de ca ??
    D'apres le man de send (http://linux.com.hk/penguin/man/2/se...an2/send.2.inc)

    -->
    Error :
    ENOTCONN
    The socket is not connected, and no target has been given.

  7. #7
    Membre habitué Avatar de BigNic
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 195
    Points : 154
    Points
    154
    Par défaut
    pour l'avoir souvent fait, je confirme send() ne fonctionne pas si ta socket ou ton descripteur sont non valide.
    Et généralement tu ne test pas d'envoyé, tu gardes plutot ton message dans un coin après tu essayes d'envoyer, si ce la foire comme tu as gardé ton message tu peux toujours ré-essayer plus tard.

  8. #8
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut
    heu, oui ... exact !
    Ben alors là, je me retrouve tout bête !

    Bon mais alors comment faire pour la tester cette socket() ?

    Parce que j'ai un thread qui tourne pour affecter le descripteur si et eulement si il estcessaire de le réaffecter.
    Le descripteur est donc global, et dans d'autres threads, on peut faire des send() dessus.
    L'idée c'est que les send() marchent toujours, car le thread de surveillance a détecté que la socket est tombée.

    @+

  9. #9
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut
    Bon le seul truc que j'ai trouvé pour avoir une détection de socket perdue, c'est de faire :
    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
     
     
    	FD_SET readfds;			
    	TIMEVAL t;
    	memset(&t, 0, sizeof(t));
     
    	FD_ZERO(&readfds);
    	FD_SET(*s, &readfds);
     
    	ret = select(0, &readfds, NULL, NULL, &t);
    	if(ret == 1)
    	{
    	   TraceError("select() failed with error %d.", WSAGetLastError());
    	   closesocket(*s);
    	   *s = 0;
    	}
    En effet tant que la socket est vivante le ret = 0, et dés qu'elle est morte il vaut 1

    @+

  10. #10
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut
    mais je trouve ça vraiment pourri !!!

  11. #11
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Mars 2006
    Messages
    38
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2006
    Messages : 38
    Points : 43
    Points
    43
    Par défaut
    Pourrait tu preciser un peu plus le contexte. Este ce que la partie qui reçoit est implementé par toi. Dans ce cas, tu peux prevoir à intervalle reguliere de lancer des echo. Si tu reçoit pas de reponses, dans ce cas, tu peux considerer que la connection est out...

  12. #12
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut
    Bonjour,

    je veux que mon thread de surveillance vérifie toutes les secondes que ma socket est bien active, sinon il se charge de re-créer la connexion vers le serveur, et donc de ré-affecter un descripteur valide à ma socket.

    Je ne veux pas créer un pooling interne (echo dont tu parles) car à mon sens ce n'est pas nécessaire.
    Par exemple un recv(socket, .... ) détecte immédiatement la perte de la socket. Alors comment ça se fait qu'avec un select() je n'arrive pas à le faire avec la manière ... car je considère que ce que j'ai fait est vraiment tout pourri, mais pour le moment ça marche ...

    @+

  13. #13
    Membre actif
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Points : 256
    Points
    256
    Par défaut
    FD_SET readfds;
    TIMEVAL t;
    memset(&t, 0, sizeof(t));

    FD_ZERO(&readfds);
    FD_SET(*s, &readfds);

    ret = select(0, &readfds, NULL, NULL, &t);
    if(ret == 1 && readfds.fd_count == 1)
    {
    //--> un évènement sur le read a eu lieu :
    // - soit il y a des données sur la socket
    // - soit la remote socket est morte
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
     
    voilà, y a 2 choix possibles ... c'est ça le problème !!
    Je vais voir ce que donne le exceptfds, et s'il est mis à 1 lorsque la socket est déconnecté, mais je pense pas

  14. #14
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Mars 2006
    Messages
    38
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2006
    Messages : 38
    Points : 43
    Points
    43
    Par défaut
    Mais d'apres le man de socket, et vu que tu es en mode connecté, normalement, si ton socket n'est plus connecté, les primitive send, recv et autre doivent renvoyer -1... Tu n'as pas essayé ça?

  15. #15
    Nouveau membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    52
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 52
    Points : 37
    Points
    37
    Par défaut Un petit truc
    Pour savoir si ta socket est mort ou s'il y a des donnes a lire, essai de faire un recv, si en retour tu as 0 ou que le buffer passse a recv une taille de 0, cela veux dire que ta socket est morte.
    C'est peut-etre pas tres propree comme methode mais ca marche.

  16. #16
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Mars 2006
    Messages
    38
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2006
    Messages : 38
    Points : 43
    Points
    43
    Par défaut
    Citation Envoyé par caesarvanou
    Pour savoir si ta socket est mort ou s'il y a des donnes a lire, essai de faire un recv, si en retour tu as 0 ou que le buffer passse a recv une taille de 0, cela veux dire que ta socket est morte.
    C'est peut-etre pas tres propree comme methode mais ca marche.
    Je suis étonné que ça marche. Tu as testé? Car recv est bloquant, enfin à moins de creer une socket non bloquante, auquel cas, il me semble qu'on peut juste savoir qu'aucunes données ne sont disponnible en lecture... Mais cela ne veut pas dire que la connection est out. Ca peu aussi vouloir dire qu'aucune donnée n'a été envoyée.

    En revanche je me suis rappelé qu'un de mes programme s'interompait si je tentait d'utiliser un socket connecté apres rupture de la connection. Et dans man socket(2), j'ai trouvé ça :
    Un signal SIGPIPE est envoyé au processus tentant d'écrire sur une socket inutilisable, forçant les programmes ne gérant pas ce signal à se terminer.
    Il y a peut etre une piste à suivre dans l'interception de ce signale....

    Bonne continuation...

  17. #17
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Pour une socket bloquante, recv() retourne zéro si la connexion a été "gentiment" fermée de l'autre coté.
    Si la connexion est "tombée" de l'autre coté, recv() retournera -1 avec une erreur ECONNRESET/WSAECONNRESET (10054)

    Par contre, le coup du zéro ne doit plus marcher quand la socket est non-bloquante (signification ambigüe).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

Discussions similaires

  1. [SOCKET] comment rendre send() bloquant
    Par damien99 dans le forum Visual C++
    Réponses: 4
    Dernier message: 23/02/2007, 16h15
  2. [Socket C#] Méthode Send
    Par adil_aeh dans le forum C#
    Réponses: 4
    Dernier message: 09/12/2006, 11h30
  3. socket & select
    Par keyra dans le forum Réseau
    Réponses: 7
    Dernier message: 29/01/2006, 16h17
  4. [SOCKET] TCP : select devant send();
    Par trois_1 dans le forum Développement
    Réponses: 4
    Dernier message: 02/03/2004, 18h10
  5. [SOCKET C] deux send() pour un recv()
    Par trois_1 dans le forum Développement
    Réponses: 4
    Dernier message: 01/12/2003, 19h13

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