Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 2 sur 2
  1. #1
    Invité de passage
    Homme Profil pro
    Inscrit en
    août 2012
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : août 2012
    Messages : 3
    Points : 0
    Points
    0

    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 :
    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 :
    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
    Chercheur d'emploi
    Inscrit en
    septembre 2007
    Messages
    5 361
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2007
    Messages : 5 361
    Points : 12 499
    Points
    12 499

    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.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •