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 :

[Socket] Serveur gérant un dialogue entre plusieurs clients


Sujet :

Réseau C

  1. #41
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par sorry60
    Qu'entends tu par "valeur des pointeur" ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       printf ("p = %p\n", (void*) p);
    Que je fais ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    #define PRT_P(p)\
       printf (#p " = %p\n", (void*) p)
    que j'utilise ainsi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
       T *pxx = ...
     
       PRT_P(pxx);

  2. #42
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 382
    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 382
    Points : 41 588
    Points
    41 588
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("%lp -> %lp ( \"%s\" )\n", unClient, unClient->login, unClient->login);
    La valeur d'un pointeur = l'adresse vers laquelle il pointe.
    Ce sera parfait pour vérifier les adresses: Comme ça, on saura si on a toujours le même client qui passe, ou s'ils pointent tous sur le même login, ou s'ils ont chacun des logins identiques...

  3. #43
    Membre actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut
    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
     
    /* on reconstitue le fds_lecture */
    					FD_ZERO(&fds_lecture);
    					unClient = deb_liste;
    					while ( unClient )
    					{
    						FD_SET(unClient->fd,&fds_lecture);
    						unClient = unClient->suivant;
    					}
    	  				if ( select(max+1,&fds_lecture,NULL,NULL,NULL) != -1 )
    	  				{
    	  					/* On se repositionne en debut de liste et on la parcourt */
    	  					unClient = deb_liste;
    	  					while( unClient )
    	  					{
    	  						printf("Client : %s\n",unClient->login);
    	  						/* Si il sait passer quelque chose dans l'emsemble de lecture avec ce client */
    	  						if ( FD_ISSET(unClient->fd,&fds_lecture))
    	  						{
    	  							printf("FD_ISSET sur %s\n",unClient->login);
    	  							printf("%p -> %p ( \"%s\" )\n", unClient, unClient->login, unClient->login);
    	  							/* Si c'est la socket d'ecoute ==> nouvelle connexion ! */
    	  							if ( unClient->fd == s_ecoute )
    	  							{
    	  								unsigned int size_client_addr = sizeof(client_addr);
    	  								SOCKET newClient = accept(s_ecoute,(struct sockaddr *)&client_addr,&size_client_addr);
    	  								int oct_rec;
    	  								if ( newClient != INVALID_SOCKET )
    	  								{
    	  									char login[16];
    	  									printf("Connexion d'un nouveau client : %s socket : %d...\n",inet_ntoa(client_addr.sin_addr),newClient);
    Je lance, connecte un premier client :
    Attente de connexion sur le port 4000...
    Client :
    FD_ISSET sur
    0x8e06008 -> 0x8048efc ( "" )
    Connexion d'un nouveau client : 127.0.0.1 socket : 4...
    Je lance un deuxieme client...
    Client :
    FD_ISSET sur
    0x8e06008 -> 0x8048efc ( "" )
    Connexion d'un nouveau client : 127.0.0.1 socket : 6...
    Voila donc la liste a bien un probleme..

  4. #44
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 382
    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 382
    Points : 41 588
    Points
    41 588
    Par défaut
    Non, ça, c'est normal, c'est la connexion.

    Ce qu'il faudrait voir, c'est ce qui se passe quand les clients envoient des messages...

  5. #45
    Membre actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut
    Citation Envoyé par Médinoc
    Non, ça, c'est normal, c'est la connexion.

    Ce qu'il faudrait voir, c'est ce qui se passe quand les clients envoient des messages...
    La reponse est rien..aucun affichage...le FD_ISSET ne donne rien

  6. #46
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 382
    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 382
    Points : 41 588
    Points
    41 588
    Par défaut
    Tu as quand même bien le message d'AVANT le FD_ISSET, non?

    (Tu as MSN? Il faudrait qu'on puisse discuter plus vite...)

  7. #47
    Membre actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut
    Citation Envoyé par Médinoc
    Tu as quand même bien le message d'AVANT le FD_ISSET, non?
    non meme pas, c'est ça le plus etrange..on dirait que le prog se bloque mais je ne trouve pas où
    en tout cas il ne rentre dans la boucle while(unClient) que lorsqu'un nouveau client se connecte...

  8. #48
    Membre actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut
    Résolu grâce à la messagerie instantanée !

    Merci à medinoc, et à tous les autres

    il me reste encore à gérer les deconnections, les mots de passe, les routages des messages, mais j'ai compris mes erreurs, je ne les referai plus.

    Bonne nuit
    A+
    Sorry

  9. #49
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par sorry60
    mais j'ai compris mes erreurs, je ne les referai plus.
    On ne saura jamais lesquelles...

  10. #50
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 382
    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 382
    Points : 41 588
    Points
    41 588
    Par défaut
    Principalement deux:
    1) une mauvaise manipulation de sa liste chaînée: il insérait au niveau du pointeur intermédiaire, puis déplaçait le début de sa liste vers la position de l'objet inséré - qui malheureusement, n'était pas inséré en début de liste - d'où problème: le test de FD_ISSET n'était même pas effectué sur certains clients
    2) une erreur de buffer injustement partagé qui faisait afficher le même login pour tous les clients (au passage, ce login était dans un tableau local qui n'était plus censé exister au moment où il était affiché).

    Je n'ai pas le code APRÈS correction, malheureusement, mais au moins, les erreurs à ne pas faire sont signalées...

  11. #51
    Membre actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Citation Envoyé par sorry60
    mais j'ai compris mes erreurs, je ne les referai plus.
    On ne saura jamais lesquelles...
    Biensur que j'allais les mettre, mais hier on a fini tard...
    Medinoc les a bien détaillées, je posterai si vous le souhaitez le code corrigé une fois que j'aurai mis un peu d'ordre dedans

  12. #52
    Membre actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut
    Salut !

    Voila j'ai remis un peu d'ordre car c'est étrange...
    Sous linux ça marche nickel, je connecte autant de clients en meme temps que je veux, je les deconnecte, reconnecte bref ça marche bien
    Par contre quand je passe sous windows, ça plante quand je deconnecte un client le select sort en erreur à chaque passage...
    select : No error
    select : No error
    select : No error
    select : No error
    ...
    Je comprends pas pourquoi sous linux s'est impec mais mais sous windows, pourtant c'est le meme code
    Voici la derniere version de la boucle infinie :
    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
     
    while(1)
    				{
    					/* on reconstitue le fds_lecture */
    					FD_ZERO(&fds_lecture);
    					unClient = deb_liste;
    					while ( unClient )
    					{
    						if ( max < unClient->fd)
    						{
    							max = unClient->fd;
    						}
         					FD_SET(unClient->fd,&fds_lecture);
    						unClient = unClient->suivant;
    					}
    	  				if ( select(max+1,&fds_lecture,NULL,NULL,NULL) != -1 )
    	  				{
    	  					/* On se repositionne en debut de liste et on la parcourt */
    	  					unClient = deb_liste;
    	  					while( unClient )
    	  					{
    	  						/* Si il sait passer quelque chose dans l'emsemble de lecture avec ce client */
    	  						if ( FD_ISSET(unClient->fd,&fds_lecture))
    	  						{
    	  							/* Si c'est la socket d'ecoute ==> nouvelle connexion ! */
    	  							if ( unClient->fd == s_ecoute )
    	  							{
    	  								unsigned int size_client_addr = sizeof(client_addr);
    	  								SOCKET newClient = accept(s_ecoute,(struct sockaddr *)&client_addr,&size_client_addr);
    	  								int oct_rec;
    	  								if ( newClient != INVALID_SOCKET )
    	  								{
    	  									char login[LOGIN_SIZE];
    	  									printf("Connexion d'un nouveau client : %s socket : %d...\n",inet_ntoa(client_addr.sin_addr),newClient);
    									  /*	if ( newClient > max )
    									  	{
    										  	max = newClient;
    									  	}*/
    	  									/* On attend la réception de son login */
    	  									oct_rec = recv(newClient,login,sizeof(login),0);
    	  									if ( oct_rec != - 1)
    	  									{
    	  										/* On procède à  l'authentification du login */
    	  										int authent = authentification(login);
    	  										if ( authent == 0 )
    	  										{
    	  											printf("Authen ok\n");
    	  											/* Authentification reussie ! */
    	  											/* On met le nouveau client dans la liste */
    	  											ajouter_client(&deb_liste,login,"",newClient);
    	  											/* On le met aussi dans l'ensemble de lecture */
    	  											FD_SET(newClient,&fds_lecture);
    	  										}
    	  										else
    	  										{
    	  											/* Client inconnu ! */
    	  											char erreur404[] = "Desole vous n'etes pas dans la base de donnees...\n";
    	  											int oct_env;
    	  											/* On envoie un message d'erreur au client inconnu */
    	  											oct_env = send(newClient,erreur404,sizeof(erreur404),0);
    	  											if ( oct_env == -1 )
    	  											{
    	  												perror("send() 404error");
    	  											}
    	  										}
    	  									}
    	  									else
    	  									{
    	  										perror("revc() login");
    	  									}
    	  								}
    	  								else
    	  								{
    	  									perror("accept()");
    	  								}
    	  							}
    	  							else
    	  							{
    	  								/* Le client en cours a fait une action ! */
    	  								int oct_rec;
    	  								char message[144];  /* 16 premiers octets pour le login du destinataire, le reste c'est le message */
     
    	  								oct_rec = recv(unClient->fd,message,sizeof(message),0);
    	  								if ( oct_rec <= 0 )
    	  								{
    	  									/* Erreur ou deconnexion client */
    	  									printf("Deconnexion de %s...\n",unClient->login);
    	  									/* On le retire de l'ensemble de lecture */
    	  									FD_CLR(unClient->fd,&fds_lecture);
    	  									/* On le retire de la liste */
    	  									retirer_client(&deb_liste,unClient->fd);
    	  								}
    	  								else
    	  								{
    	  									/* Le client a envoye un message ! */
    	  									printf("%s a envoyé %d octets !\n",unClient->login,oct_rec);
    	  								}
    	  							}
    	  						}
    	  						unClient = unClient->suivant;
    	  					} /* Fin du parcour de la liste */
    	  				}
    	  				else
    	  				{
    	  					perror("select()");
    	  				}
    	  			} /* Fin de la boucle infinie */

  13. #53
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 382
    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 382
    Points : 41 588
    Points
    41 588
    Par défaut
    Ce n'est peut-être pas ça, mais ça a des chances d'être lié:
    Sous Windows, il te faut remplacer le close() par un closesocket().
    (Car sous Windows, un socket n'est PAS un descripteur, et close() ne marche que sur les descripteurs).

    En regardant mieux ton code: Ben, c'est pas sûr que ce soit ça, puisqu'il est retiré de la liste de toute façon, et du fd_set aussi...
    Mais tu devrais penser à le fermer quand même... (je n'ai vu ni close(), ni closesocket())

    Ce que je te conseille, c'est un truc du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #ifdef unix
    #define CLOSE_SOCKET(s) close(s)
    #else
    #define CLOSE_SOCKET(s) closesocket(s)
    #endif
    Puisque closesocket() n'est pas déclaré sous unixoïde...
    Alors dans ton code, tu n'as plus qu'à mettre un CLOSE_SOCKET(fd)...

  14. #54
    Membre actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut
    Ah oui c'est clair je ne ferme aucune socket
    Je vais essayer ça, merci !

  15. #55
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Médinoc
    Ce que je te conseille, c'est un truc du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #ifdef unix
    #define CLOSE_SOCKET(s) close(s)
    #else
    #define CLOSE_SOCKET(s) closesocket(s)
    #endif
    Puisque closesocket() n'est pas déclaré sous unixoïde...
    Alors dans ton code, tu n'as plus qu'à mettre un CLOSE_SOCKET(fd)...
    http://emmanuel-delahaye.developpez....ck/inc/psock.h

  16. #56
    Membre actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut
    Aie, j'ai corrigé mon code en fermant la socket à chaque déconnexion, mais le bug est toujours là..
    Ce qui est bizarre c'est aussi le message de errno :
    socket() : No error
    Select renvoie -1 mais errno ne contient pas d'erreur
    Et c'est propre à windows

  17. #57
    Membre actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut
    J'ai rajouté un printf pour afficher le code d'erreur de select au moment de son plantage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    else
    {
       perror("select()");
       printf("errno = %d\n",errno);
    }
    Etrangement le code d'erreur est 0...
    select() : No error
    errno = 0
    Hors si je me refaire à la page man de errno, errno ne peut pas être nul si il y a une erreur..
    Les codes d'erreurs valides sont tous non-nuls. errno n'est jamais mis à zéro par une fonction de la bibliothèque. Toutes les erreurs détaillées dans POSIX.1 doivent avoir des valeurs différents.
    C'est donc windows qui pète un cable ? (pour changer...)

  18. #58
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par sorry60
    Aie, j'ai corrigé mon code en fermant la socket à chaque déconnexion, mais le bug est toujours là..
    Ce qui est bizarre c'est aussi le message de errno :
    socket() : No error
    Select renvoie -1 mais errno ne contient pas d'erreur
    Et c'est propre à windows
    Il faut appeler WSAGetLastError(). La portabilité Linux/Windows est limitée...

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/wsagetlasterror_2.asp

  19. #59
    Membre actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut
    DWORD GetLastError( void );
    On affiche comment un DWORD ?

  20. #60
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par sorry60
    DWORD GetLastError( void );
    On affiche comment un DWORD ?
    D'après la doc de MS, c'est un entier non signé, alors "%lu" avec (unsigned long)

    Pour la sémantique :

    http://emmanuel-delahaye.developpez....src/wsatools.c

Discussions similaires

  1. Plusieurs socket cliente sur une socket serveur en Java?
    Par loic911 dans le forum Développement
    Réponses: 3
    Dernier message: 11/06/2010, 08h47
  2. Dialogue entre serveur et client
    Par Carrel dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 03/07/2009, 07h48
  3. problème lors d'un dialogue entre client et serveur
    Par Dave62 dans le forum Réseau
    Réponses: 3
    Dernier message: 10/12/2008, 10h24
  4. Réponses: 3
    Dernier message: 31/10/2006, 11h34
  5. [Socket] Probleme entre un Client C et un serveur JAVA
    Par bpy1401 dans le forum API standards et tierces
    Réponses: 3
    Dernier message: 28/02/2006, 09h40

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