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 non bloquant


Sujet :

C++

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 8
    Points : 4
    Points
    4
    Par défaut socket non bloquant
    Tout est dans le titre, j'arrive pas a faire de mon socket, un socket non bloquant, voici le code de la fonction pour recevoir le message du serveur.
    La variable readfds etant de type fd_set
    La variable socket est de type SOCKET est bien initialisé car j'arrive a recevoir des messages quand j'en envoie

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int Server::recevoir_message()
    {
    	message = new char[1024];
    	int result = 0;
    	FD_ZERO(&readfds);
    	FD_SET(socket,&readfds);
    	select(0,&readfds,0,0,NULL);
    	if(FD_ISSET(socket, &readfds))
    	{
    		result = recv ( socket, message , 1024 , 0 ) ;
    	}
    	return result;
    }
    Lorsque je lance cette fonction dans une boucle, la boucle se bloque si le serveur aucun message n'est reçu.
    Apparemment le bloquage se fait au niveau du select d'apres mes tests.
    Si vous pouvez eclairer ma lanterne ca serait sympa ! Merci d'avance.

  2. #2
    Nouveau membre du Club
    Inscrit en
    Mai 2007
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 26
    Points : 28
    Points
    28
    Par défaut
    La socket doit être mis non bloquante après sa déclaration, voici la fonction classique pour le faire qui est utilisé dans beaucoup de tuto et qui a le mérite d'être cross-platform.
    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
     
    /*----------------------------------------------------------------------
     Portable function to set a socket into nonblocking mode.
     Calling this on a socket causes all future read() and write() calls on
     that socket to do only as much as they can immediately, and return 
     without waiting.
     If no data can be read or written, they return -1 and set errno
     to EAGAIN (or EWOULDBLOCK).
     Thanks to Bjorn Reese for this code.
    ----------------------------------------------------------------------*/
    int setNonblocking(int fd)
    {
        int flags;
     
        /* If they have O_NONBLOCK, use the Posix way to do it */
    #if defined(O_NONBLOCK)
        /* Fixme: O_NONBLOCK is defined but broken on SunOS 4.1.x and AIX 3.2.5. */
        if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
            flags = 0;
        return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
    #else
        /* Otherwise, use the old way of doing it */
        flags = 1;
        return ioctl(fd, FIOBIO, &flags);
    #endif
    }

  3. #3
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Normal, la fonction select bloque jusqu'à ce qu'il y ait des données à lire.

  4. #4
    Nouveau membre du Club
    Inscrit en
    Mai 2007
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 26
    Points : 28
    Points
    28
    Par défaut
    Oops j'avais même pas lu jusqu'au bout, si tu ne veux pas que select bloc plus d'un certain temps, pour continuer à executer une routine par exemple dans un programme non threadé, tu peux spécifier un timeout à la fonction select.

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 8
    Points : 4
    Points
    4
    Par défaut
    Vous auriez un exemple plus au moins complet avec declaration de socket, mise en non bloquant et un timeout pour le select parce que j'ai du mal à visualiser la.

    En tout cas merci pour l'aide jusque là.

  6. #6
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Lis ton manuel unix, ça t'expliquera comment select fonctionne.

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 8
    Points : 4
    Points
    4
    Par défaut
    je suis sur windows avec visual C++

    Puis j'ai pas besoin qu'on me réponde pour me dire une chose pareil, ca n'a pas d'interet...

  8. #8
    Nouveau membre du Club
    Inscrit en
    Mai 2007
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 26
    Points : 28
    Points
    28
    Par défaut
    Les socket du monde windows sont casi identique à celle du monde UNIX, si je me trompe pas windows utiliserai du code BSD pour sa partie réseau ?
    J'ai commencé sur les socket avec un exelent tutorial qui est pour moi la référence en la matière, le tutorial de Beej.

  9. #9
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Voir également le site d'Emmanuel Delahaye : http://emmanuel-delahaye.developpez.com/reseaux.htm

  10. #10
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 8
    Points : 4
    Points
    4
    Par défaut
    Je vous remercie pour ces tutoriaux, mais hélas ils ne font que confirmer pourquoi je poste. C'est à dire que je pense que ca devrait marcher mais ca marche pas

    voici le code que j'aie a l'initialisation peut etre que le problème vient de la.
    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
     
    int Server::connection()
    {
    	tv.tv_sec = 2;
    	tv.tv_usec = 500000;
     
        int nonblocking=0;
     
    	/* ouverture d'un socket de communication */
    	if ( ( _socket = socket ( AF_INET , SOCK_STREAM , 0 ) ) == -1 )
    	{
    		return 0;
    	}
     
    	printf ( "Socket numero %d cree\n" , _socket ) ;
     
    	ioctlsocket( _socket, FIONBIO, (unsigned long*) &nonblocking);
     
    	/* Connexion au Serveur */
    	if ( connect ( _socket , (struct sockaddr*)&(_sockaddr) , sizeof (struct sockaddr_in) ) )
    	{
    		return 0;
    	}
     
    	printf ( "Connect OK\n" ) ;
     
    	return 1;
    }

    Et comme je l'ai dit précedemment, si je recois des messages tout fonctionne le probleme se situe au niveau du select qui ne veut pas etre non bloquant

  11. #11
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    C'est normal que ça bloque... Select est bloquant sur ton socket...

    Sinon, passes en paramètre à select un struct timeval que tu initialises ainsi :
    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
     
    /*définition dans winsock2.h*/
    struct timeval {
    	long    tv_sec;
    	long    tv_usec;
    };
     
     
     
    /*initialisation*/
    struct timeval t;
    t.tv_sec = 0;
    t.tv_usec = 0;
     
    select(, ...., &t);

  12. #12
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 8
    Points : 4
    Points
    4
    Par défaut
    bon, je tiens a m'excuser pour la perte de temps que j'ai pu faire et remercier les personnes qui m'ont aidé.

    Mon problème venait que je definissais mon time out mais je ne le mettais pas dans le select .............

    Donc voila encore Merci !!!

  13. #13
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 107
    Points : 82
    Points
    82
    Par défaut
    bonjour

    je suis entrain de faire la meme chose
    comme as tu déclaré readfds, svp?

  14. #14
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Citation Envoyé par untipy
    bonjour

    je suis entrain de faire la meme chose
    comme as tu déclaré readfds, svp?

    Il a écrit que c'était de type fd_set :
    Donc quelque chose du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    fd_set readfs;
    FD_ZERO(&readfs);
     
    //on ajoute les socket à regarder
    FD_SET(socket, &readfs);
    ....

  15. #15
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 107
    Points : 82
    Points
    82
    Par défaut
    voila ! j'ai un truc comme çà:
    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
     fd_set rfds;
                struct timeval tv;
                int retval;
                FD_ZERO(&rfds);
                FD_SET(sck, &rfds); /* on ajoute la socket a regarder */
                tv.tv_sec = 2;
                tv.tv_usec = 0;
                retval = select(0, &rfds, NULL, NULL, &tv);
     
                if (retval)
                {
                    /* infos reçues sur sck dans les 2 secondes*/
                    len = read(sck,msg,4096);
    }
    else{printf"rienr recu");}
    mais il détecte jamais rien en entrée du socket

  16. #16
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Il faut utiliser FD_ISSET pour savoir si des données sont arrivés sur le socket.

    Il faut aussi tester retval avec des chiffres :
    -1 = erreur
    0 = timeout dépassé
    n = nombre de socket (ou de file descriptor) qui a recu des données

  17. #17
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 107
    Points : 82
    Points
    82
    Par défaut
    oui vous avez raison :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (FD_ISSET(sck, &rfds))
    j'avais bien testé çà

    merci pour vos conseils !!

    je pense que cela vient de la configuration de mon select
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    retval = select(0, &rfds,0, 0, &tv);
    Qaund le premier parametre est 0, le timer ne fonctionne pas mais lit le socket
    Qaund le premier parametre est 1, le timer ne fonctionne mais ne lit le socket

    ou alors c'est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     FD_SET(me->sock, &rfds);
    qui n'ajoute pas le descripteur
    >> >>

  18. #18
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 107
    Points : 82
    Points
    82
    Par défaut
    Voila j'ai trouvé mon buf .... oufff
    alors petit retour d'expérience si cela peut être utile a d'autres programmeurs ...

    je suis sur linux
    donc pour faire une socket non bloquant en lecture, il faut configurer la fonction select
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int select( int nfds,fd_set* readfds,fd_set* writefds,fd_set* exceptfds,const struct timeval* timeout );
    sachant que nfds : [doit valoir le plus grand identifiant de socket, plus 1 (non utilisé sous Windows).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int select( socket+1,...)
    Le plus 1 est SUPER important, c'était mon bug.

  19. #19
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Citation Envoyé par untipy
    Le plus 1 est SUPER important, c'était mon bug.
    Oui, j'avais oublié de signalé ce détail

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

Discussions similaires

  1. Socket non bloquant
    Par Shredder dans le forum Web & réseau
    Réponses: 1
    Dernier message: 29/10/2007, 11h44
  2. [timer & thread] timeout & socket non bloquant
    Par untipy dans le forum Réseau
    Réponses: 33
    Dernier message: 22/08/2007, 08h37
  3. [Réseau] socket non bloquant
    Par beLz dans le forum Réseau
    Réponses: 2
    Dernier message: 28/07/2007, 15h20
  4. Réponses: 3
    Dernier message: 20/10/2006, 19h50
  5. socket non bloquante
    Par jeje99 dans le forum Réseau
    Réponses: 15
    Dernier message: 21/02/2006, 08h52

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