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

C++ Discussion :

socket et timers....


Sujet :

C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    98
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 98
    Points : 75
    Points
    75
    Par défaut socket et timers....
    Salut!!
    J'ai un petit probleme de temporisation de mes sockets. J'ai pas vraiment trouvé ce que je cherchais dans les posts précédents alors... me voici.


    Je developpe un client qui se connecte à un serveur. (Oui, ca valait le coup de l'écrire)
    Donc je repere la connexion et puis j'attends des données émises par le serveur. Pbm. Il se peut que le serveur accepte la connexion et n'envoie rien. En quel cas le client attend indéfiniment pendant très longtemps voir infiniment.
    Bref, je voudrais mettre en place un systeme qui fait que si rien n'est recu pendant une certaine durée alors, on ferme la connexion et puis basta...

    Alors pour les détails maintenant:

    je travail en VC6
    mon recv est bloquant.
    et voici un extrait de mon code, ou je voudrais intervenir

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    while(this->getEstConnecte() == true)
    {
           int out = recv(this->getSocketDescriptor(), this->buffer,TAILLE_MESSAGE,0);
           if(out == TAILLE_MESSAGE_WB)
           {
                //blabla
           }
           else
               //blablabla
    }
    Je voudrais armer un timer avant le recv, le stopper apres, et faire des choses si jamais je ne recois rien dans le temps imparti. Si possible, j'aimerais garder un maximum de visibilité sur mon "environmement" dans ce bout de code. Le code que je vous ai donné est un extrait d'une fonction membre d'un classe. J'aimerais encore avoir la visibilité sur la classe lorsque je detecte une non reception.....

    J'ai bien une solution envisageable qui constituerait à lancer un thread en parallele et mettre en place des events mais ca me parait un peu lourd pour une si petite chose. Je suis sur qu'il y a plus simple mais je sais pas ce que c'est..

    Voila. J'ai fait aussi clair que possible. Enfin si vous voulez plus de détail, je suis pret à vous aidez pour que vous puissiez m'aider.......

    Merci beaucoup de votre soutien..


    Sebastien.

  2. #2
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut
    je ne connais pas recv() mais, il n'y a pas moyen de faire un appel non bloquant ? auquel cas, il te suffirait de faire une boucle avec un sleep() ou un truc de ce genre.

  3. #3
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 751
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 751
    Points : 10 670
    Points
    10 670
    Billets dans le blog
    3
    Par défaut
    Regarde du côté de select et en particulier de son dernier paramètre. Sinon utilise des socket asynchrone (spécifique Windows).

  4. #4
    Membre habitué
    Profil pro
    Enculeur de mouches
    Inscrit en
    Septembre 2003
    Messages
    133
    Détails du profil
    Informations personnelles :
    Localisation : France, Creuse (Limousin)

    Informations professionnelles :
    Activité : Enculeur de mouches

    Informations forums :
    Inscription : Septembre 2003
    Messages : 133
    Points : 161
    Points
    161
    Par défaut
    Voici un truc qui risquerait de marcher, à condition d'utiliser un system POSIX complient.
    On peut programmer des horlorges via la fonction sigaction et le signal SIGALRM.

    voici un p'tit exemple

    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
     
    #include <signal.h>
    #include <unistd.h>
    #include <errno.h>
    #include <stdio.h>
     
    void doNothing(int) {} // dans cette function le code d'interruption sur alarme eventuel
     
    int main (void) {
      struct sigaction action;
      char input;
      int nb;
      unsigned int r;
     
      sigemptyset(&(action.sa_mask));
      action.sa_flags=0;
      action.sa_handler=doNothing;
      sigaction(SIGALRM, &action, (struct sigaction*)0); // install du gestionnaire
      fprintf(stdout, "Input? "); fflush(stdout);
      alarm(10);                                                                 // delai 10s max.
      nb = read(STDIN_FILENO, &input, sizeof(char));     // lire saisie utilisateur APPEL BLOQUANT !!!
      r = alarm(0);                                                             // lecture temps restant  
      if ((nb!=sizeof(char)) && (errno==EINTR)) printf("Too late!!!\n");
         else printf("OK  --> %c ; %u seconds remaining", input, r);
     
      return(0);
    }

    Voilà donc, un appel système bloquant interrompu par une interruption (sic!!)... Le code exécuté à l'expiration du délais est -au besoin- inclus dans doNothing() (ou tout autre nom qu'on peut lui donner, évidemment).
    Bon en l'occurence, vu que le programme poursuit son exécution, on peut tester, comme ici, si le délais est expiré ou non et agir en conséquence (i.e. fermer les sockets ou communiquer ave le serveur).

    En espérant que ça te sera utile, et en remerciant mon ancien prof de Prog Système, le sublime Fabrice Harrouët...
    Gaïa n'est pas une marchandise.

  5. #5
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 751
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 751
    Points : 10 670
    Points
    10 670
    Billets dans le blog
    3
    Par défaut
    Voilà donc, un appel système bloquant interrompu par une interruption (sic!!)...
    Je comprends pas comment ça marche, pourquoi l'appel à read est débloqué.

  6. #6
    Membre habitué
    Profil pro
    Enculeur de mouches
    Inscrit en
    Septembre 2003
    Messages
    133
    Détails du profil
    Informations personnelles :
    Localisation : France, Creuse (Limousin)

    Informations professionnelles :
    Activité : Enculeur de mouches

    Informations forums :
    Inscription : Septembre 2003
    Messages : 133
    Points : 161
    Points
    161
    Par défaut
    En fait ce qui est clair c'est que ça ne marche que pour des fonctions systèmes qui retourne en cas d'interruption. La spec de read() (man 2 read) indique qu'en cas de reception de signaux par le programme, elle retourne, avec errno==EINTR.
    La preuve : (page man)
    VALEUR RENVOYÉE
    read renvoie -1 s'il échoue, auquel cas errno contient le code
    d'erreur, et la position de la tête de lecture est indéfinie.

    Sinon, read renvoie le nombre d'octets lus [...]
    ERREURS
    EINTR read a été interrompu par un signal avant d'avoir eu le temps
    de lire quoi que ce soit.
    page man de recv :
    EINTR Un signal a interrompu la lecture avant que des données soient
    disponibles.
    Donc pas de soucis ça marche !!!
    Gaïa n'est pas une marchandise.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    98
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 98
    Points : 75
    Points
    75
    Par défaut
    Oui, ca m'a l'air pas mal. Je vais regarder dans cette direction.
    Merci à toi et à Fabrice Harrouët donc.


    Juste un dernier point:

    Je peut invoquer une méthode de classe à la place de ton doNothing?
    Si oui: faut il qu'elle soit déclarée de maniere particuliere (static sans doute)?
    Si oui: puis je lui passer explicitement le pointeur implicite this?

    Tout ceci dans le but de pouvoir dans la fonction doNothing fait qq chose du genre:
    this->FermerMoiCetteConexionSVP()



    Merci encore pour les infos.

  8. #8
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 751
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 751
    Points : 10 670
    Points
    10 670
    Billets dans le blog
    3
    Par défaut
    Mais y'a plusieurs types de signaux. Je pensais que read( STDIN )n'était débloqué que part CTRL+D (EOF).

  9. #9
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 751
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 751
    Points : 10 670
    Points
    10 670
    Billets dans le blog
    3
    Par défaut
    Je ne cherche pas à imposer ma solution, mais passer par select qui est d'avantage portable et me parrait plus simple à comprendre (le code du timeout est juste en dessous du select et non ailleurs quelque part dans une fonction callback) me semble mériter le coup d'oeil.
    http://www.erlenstar.demon.co.uk/unix/faq_3.html#SEC26

  10. #10
    Membre habitué
    Profil pro
    Enculeur de mouches
    Inscrit en
    Septembre 2003
    Messages
    133
    Détails du profil
    Informations personnelles :
    Localisation : France, Creuse (Limousin)

    Informations professionnelles :
    Activité : Enculeur de mouches

    Informations forums :
    Inscription : Septembre 2003
    Messages : 133
    Points : 161
    Points
    161
    Par défaut
    Perso je te conseille d'appeller la méthode classe dans le bloc du if(..) à la place de printf("Too late!!!\n").
    Tes remarques sont justes mais j'ai buté sur le problème en essayant de coder une classe Cthread, et le problème est toujours ouvert pour moi, j'ai jamais réussi qu'à obtenir des seg fault au lancement des threads...

    Si tu veux persister, néanmoins, dans cette voie, ben le soucis est pas simple... Dans le cas des threads on passe un void* à la fonction d'init, ce qui permet de récupérer un structure contenant le this de l'objet Thread concerné, mais là... J'veux bien y refléchir si tu veux mais la première solution me parrait quand même plus simple...

    Aurelien.Regat-Barrel >> A ma connaissance, EOF n'est pas un signal stricto sensus (i.e. un entier envoyé par un processus (eventuellemnt le kernel) à un autre, entier codé par les macros SIGALRM, SIGABORT, SIGSEGV, SIGVTALARM, etc...) alors qu'EOF est un caractère spécial transitant par un flux ou un file descriptor...
    Effectivement ta soluce à l'air pas mal non plus, y'a pas a dire !!!!
    Gaïa n'est pas une marchandise.

  11. #11
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 751
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 751
    Points : 10 670
    Points
    10 670
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par SKZ81
    A ma connaissance, EOF n'est pas un signal stricto sensus (i.e. un entier envoyé par un processus (eventuellemnt le kernel) à un autre, entier codé par les macros SIGALRM, SIGABORT, SIGSEGV, SIGVTALARM, etc...) alors qu'EOF est un caractère spécial transitant par un flux ou un file descriptor...
    CTRL-D aboutit à EOF, mais je ne sais pas si CTRL-D est directement traduit en EOF par la console (donc pas un signal), ou si c'est bien un signal que le handler par défaut traduit en EOF...

  12. #12
    Membre régulier
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    98
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 98
    Points : 75
    Points
    75
    Par défaut
    select, c'est Nickel

    Merci a tous!!

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

Discussions similaires

  1. Socket client pendant un timer
    Par stc074 dans le forum Applets
    Réponses: 4
    Dernier message: 01/10/2010, 21h08
  2. [timer & thread] timeout & socket non bloquant
    Par untipy dans le forum Réseau
    Réponses: 33
    Dernier message: 22/08/2007, 08h37
  3. executer une application a distance : Sockets ? RPC ? CORBA?
    Par a_hic dans le forum Développement
    Réponses: 5
    Dernier message: 30/05/2006, 13h02
  4. Socket:Envoyer du texte d'un serveur vers tout les clients
    Par cedm78 dans le forum Web & réseau
    Réponses: 7
    Dernier message: 01/08/2002, 16h40
  5. transfert d'un fichier bitmap en socket tcp
    Par localhost dans le forum C++Builder
    Réponses: 5
    Dernier message: 29/07/2002, 00h40

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