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 :

Un select qui ne se bloque plus


Sujet :

Réseau C

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

    Informations forums :
    Inscription : Août 2012
    Messages : 3
    Points : 3
    Points
    3
    Par défaut Un select qui ne se bloque plus
    Bonjour !
    Alors voilà, je code une application serveur pour un petit jeu de pendu (la partie jeu n'est pas bien au point dans le code mais ça n'est pas important).
    Le problème est que mon select, après un premier blocage/attente d'une première identification d'un client, ne bloque plus rien (alors que le client se déconnecte après opération).

    Ce qui devrait se passer :
    - Un client se connecte
    - Le serveur l'ajoute à une liste des clients
    - Le client envoie une données (chaîne de caractères)
    - Le serveur enregistre cette données
    - Le serveur attend la suivante
    - etc.

    Alors qu'en résumé j'ai, après connexion du client :
    - Un serveur qui tourne en boucle comme si des clients lui envoyait des données (select qui ne bloque pas)
    - Tous mes clients déconnectés (donc aucune modification des fd des sockets)

    Le code serveur (en court) :
    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
     
    //Je passe les détails de l'initialisation de la socket serveur...
    SOCKET sock_max = sock_serveur;
    	while (!mot_trouve)
    	{
    		FD_ZERO (&fd_joueurs); /* Remise à zéro des file descriptor*/
    		FD_SET (sock_serveur, &fd_joueurs); /* Ajout de la socket d'écoute à l'ensemble des file descriptor */
     
    		liste_joueur * liste_joueurs_temp = liste_joueurs;
    		/* Ajout des sockets client à l'ensemble des file descriptor */
    		while(liste_joueurs_temp) //Oui oui, j'ai une liste de joueurs
    		{
    			FD_SET(liste_joueurs_temp->le_joueur->sock, &fd_joueurs); 
    			liste_joueurs_temp = liste_joueurs_temp->suivant;
    		}
     
    		/* Ecoute des sockets */
    		if ((select (sock_max+1, &fd_joueurs, NULL, NULL, NULL)) == ERREUR_SOCKET) 
    			erreur("select");
     
    		/* Connexion d'un joueur */
    		if (FD_ISSET (sock_serveur, &fd_joueurs)) /* Une tentative de connexion à la socket d'écoute */
    		{
    			struct sockaddr_in sock_joueur_info;	/* Infos sur le joueur */
    			SOCKET joueur_sock;
    			if((joueur_sock = accept(sock_serveur, (struct sockaddr*)&sock_joueur_info, &taille_sock_serveur_info))== ERREUR_SOCKET) /* On accepte l'écoute */
    				erreur("accept");
     
    			/* Paramètres du joueur */
    			if(recv(joueur_sock, buffer, TAILLE_BUFFER*sizeof(char), 0) == ERREUR_SOCKET)
    				erreur("recv");
     
    			/* Création du nouveau joueur */
    			struct joueur  * nouveau_joueur;
    			nouveau_joueur = malloc(sizeof(struct joueur));
    			nouveau_joueur->sock = joueur_sock;
    			nouveau_joueur->ip = inet_ntoa(sock_joueur_info.sin_addr);
    			nouveau_joueur->coupsRestant = COUP_JOUER_MAX;
    			strncpy(nouveau_joueur->nom, buffer, TAILLE_BUFFER*sizeof(char));
     
    			/* Affiche qu'un nouveau client s'est connecté au serveur */
    			fprintf(stderr,"%s ; %s a rejoint la partie.\n", nouveau_joueur->ip, nouveau_joueur->nom);
     
    			/* Envoie le mot au joueur */
    			strncpy(buffer, mot_a_trouve_masque, TAILLE_BUFFER*sizeof(char));
    			fprintf(stderr,"envoi du mot : %s\n", mot_a_trouve_masque);
    			if(send(nouveau_joueur->sock, buffer, TAILLE_BUFFER*sizeof(char), 0 ) == ERREUR_SOCKET) 
    				erreur("send");
     
    			/* Ajout du joueur à la liste des joueurs */
    			liste_joueurs = ajout_en_tete(liste_joueurs, nouveau_joueur);
     
    			/* Recalcule de la socket maximale */
    			if(sock_max < joueur_sock)
    				sock_max = joueur_sock;
     
    			FD_SET(joueur_sock, &fd_joueurs);
    		}
    		else /* Message reçu d'un client */
    		{ //Ici rien n'est au point, je l'ai laissé au cas où mon erreur s'y trouvait
    			liste_joueurs_temp = liste_joueurs;
    			/* Ajout des sockets client à l'ensemble des file descriptor */
    			while(liste_joueurs_temp) 
    			{
    				/* Vérification du joueur */
    				if(FD_ISSET(liste_joueurs_temp->le_joueur->sock, &fd_joueurs)); 
    				{
    					/* Vérification si le mot à trouver existe */
    					if(strcmp(mot_a_trouve, ""))
    					{
    						if(recv(liste_joueurs_temp->le_joueur->sock, buffer, TAILLE_BUFFER*sizeof(char), 0) == ERREUR_SOCKET)
    							erreur("recv");
    						fprintf(stderr,"Mot recu : %s\n", buffer);
    						strncpy(mot_a_trouve, buffer, TAILLE_BUFFER*sizeof(char));
    						int numero_lettre = 0;
    						/* Le mot à trouver devient celui envoyé par le joueur */
    						while(mot_a_trouve[numero_lettre] != '\0')
    						{
    							mot_a_trouve_masque[numero_lettre] = '-';
    							numero_lettre++;
    						}
    						mot_a_trouve_masque[numero_lettre+1] = '\0';
    					}
    					else
    					{
    						if(recv(liste_joueurs_temp->le_joueur->sock, buffer, TAILLE_BUFFER*sizeof(char), 0) == ERREUR_SOCKET)
    							erreur("recv");
    						/* Si le joueur propose une lettre */
    						if(buffer[1]=='\0')
    						{
    							int numero_lettre = 0;
    							while(mot_a_trouve[numero_lettre] != '\0')
    							{
    								if(mot_a_trouve[numero_lettre] == buffer[0])
    								{
    									mot_a_trouve_masque[numero_lettre] = buffer[0];
    									strncpy(mot_a_trouve_masque, buffer, TAILLE_BUFFER*sizeof(char));
    									liste_joueur * liste_joueurs_temp_2 = liste_joueurs;
    									while(liste_joueurs_temp_2)
    									{
    										if(send(liste_joueurs_temp_2->le_joueur->sock, buffer, TAILLE_BUFFER*sizeof(char), 0 ) == ERREUR_SOCKET) 
    											erreur("send");
    										liste_joueurs_temp_2 = liste_joueurs_temp_2->suivant;
    									}
    								}
    								numero_lettre++;
    							}
    						}
    						else /* Si le joueur propose un mot */ 
    						{
     
    							liste_joueurs_temp->le_joueur->coupsRestant = 0;
    						}
    					}
    					break;
    				}
    				liste_joueurs_temp = liste_joueurs_temp->suivant;
    			}
    			fprintf(stderr,"Jusque là ça marche !\n");
    			sleep(1);
            }
     
    		/* Le mot a été trouvé */
    		if(mot_trouve == VRAI)
    		{
    			while(liste_joueurs) 
    			{
    				strcpy(buffer, "Fin de partie !\n");
    				if(send(liste_joueurs->le_joueur->sock, buffer,  TAILLE_BUFFER*sizeof(char), 0 ) == ERREUR_SOCKET) 
    					erreur("send");
    				close_socket(liste_joueurs->le_joueur->sock);
    				liste_joueurs_temp = liste_joueurs_temp->suivant;
    			}
    			detruire_liste(liste_joueurs);
    			close_socket(sock_serveur);
    			break;
    		}
        }
    Le code client (pareil) :
    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
    //Rien de fou dans le code client. Je l'ai mis aussi, au cas où...
    	if(connect(sock, (SOCKADDR*)&sock_info, sizeof(sock_info)) != ERREUR_SOCKET)
    	{
    		fprintf(stderr,"Connexion à %s sur le port %d\n", inet_ntoa(sock_info.sin_addr), htons(sock_info.sin_port));
    		int i=0;
    		while(i<12)
    		{
    			strncpy(buffer, nom, TAILLE_BUFFER*sizeof(char));
    			if(send(sock, buffer, TAILLE_BUFFER, 0)== ERREUR_SOCKET)
    				erreur("send");
    			if(recv(sock, buffer, TAILLE_BUFFER, 0) == ERREUR_SOCKET)
    				erreur("send");
    			fprintf(stderr,"Recu : %s\n", buffer);
    			if (strcmp(buffer,"")==0)
    			{
    				fprintf(stderr,"Veuillez choisir un mot, vous êtes le leader :\n");
    				scanf ("%s", buffer);
    				if(send(sock, buffer, TAILLE_BUFFER, 0)== ERREUR_SOCKET)
    					erreur("send");
    				break;
    			}
    			else
    			{
    				i++;
    				fprintf(stderr,"Le mot est : %s\nProposez une lettre :\n",buffer);	
    				scanf ("%s", buffer);
    				if(send(sock, buffer, TAILLE_BUFFER, 0)== ERREUR_SOCKET)
    					erreur("send");
    			}
    		}
    	}
    	/* sinon, on affiche "Impossible de se connecter" */
    	else
    	{
    		fprintf(stderr,"Impossible de se connecter\n");
    	}
    	fprintf(stderr,"Fin de partie\n");
    	/* On ferme la socket */
    	close_socket(sock);
     
        /* On attend que l'utilisateur tape sur une touche, puis on ferme */
        getchar();
     
        return EXIT_SUCCESS;
    }
    Ai-je mal configuré mon select ? Je n'arrive pas à trouver de réponse... Cela fait quelques jours que je bloque dessus.
    Merci beaucoup à tous !

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 370
    Points : 23 625
    Points
    23 625
    Par défaut
    Hello,

    Bien que les extraits que tu nous présentes soient relativement bien fournis, il nous manque quand même pas mal de choses pour être affirmatifs : notamment, les endroits où sont définis ERREUR_SOCKET et autres.

    Quoi qu'il en soit, il y a plusieurs choses qui peuvent amener un select() à ne pas bloquer :

    • Une erreur. Quelle qu'elle soit. Vérifie notamment si ERREUR_SOCKET a la bonne valeur pour voir si tu détectes bien les erreurs et, si c'est le cas, à vérifier laquelle. Notamment, select() peut échouer s'il doit surveiller un descripteur invalide. Par exemple, celui d'un client que tu aurais déjà refermé ;
    • Un valeur sock_max invalide. Si tu reçois des clients a posteriori, il y a de fortes chances pour que le numéro de leur descripteur soit supérieur au socket initial servant à recevoir les connexions entrantes. Il faut le remettre à jour au début de ta boucle lorsque tu réinitialises fd_set ;
    • Un signal reçu. Peu probable dans ton cas ;
    • La fermeture normale d'un des sockets surveillés. Dans ce cas, tu reçois un paquet en lecture d'exactement zéro octet. Il s'agit d'une déconnexion du client et il faut traiter ce cas ;
    • Un paquet non lu ! Si select() débloque parce que quelque chose à lire est arrivé et que tu ne lis pas ces données, le prochain appel ne bloquera pas ;
    • Un paramètre NONBLOCK passé explicitement. Ça n'a pas l'air d'être le cas ici.


    À toi de voir, donc.

Discussions similaires

  1. Réponses: 3
    Dernier message: 04/07/2012, 13h33
  2. un SELECT qui retourne plus de ligne que la table
    Par gomodo dans le forum Langage SQL
    Réponses: 6
    Dernier message: 29/10/2007, 14h17
  3. Select qui boucle ou se termine par un Ora-01460
    Par PatriceP dans le forum Oracle
    Réponses: 4
    Dernier message: 29/10/2004, 08h53
  4. Pb de selection qui ne se fait pas
    Par Stef.proxi dans le forum Langage SQL
    Réponses: 4
    Dernier message: 06/08/2004, 10h54
  5. 2 SELECT Qui ne s'entendent pas très bien entre eux :(
    Par moutanakid dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 05/08/2004, 16h46

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