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 :

utilisation de select() pour faire un Tchat


Sujet :

Réseau C

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 189
    Points : 60
    Points
    60
    Par défaut utilisation de select() pour faire un Tchat
    Bonjour,

    je suis entrain de faire un Tchat en TCP. Le serveur doit pouvoir accepter plusieurs connections de clients. Pour celà j'utilise la fonction select() mais je ne suis pas certain de savoir commet elle fonctionne ... il faut la mettre avant le accept() ? après ?

    voici mon serveur, si vous pouviez m'éclairer ça seait sympa.

    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
    #include "fonc_socket.h"
     
     
    int main(char * argv[], int argc)
    {
    	int s_ecoute = createBindInetSocket(SOCK_STREAM,1234) ;
    	char c ;
    	struct sockaddr_in client;
    	struct hostent * h ;
    	int fd ;
     
    	int lg = sizeof(struct sockaddr_in) ;
     
     
     
    	if (listen(s_ecoute,10)<0)
    	{
    		perror("erreur listen") ;
    		return(-2) ;
     
    	}
    	else
    	{	printf("listen réussi \n") ;
    		//printf("Serveur lancé ! En attente de messages ...\n") ;
     
     
    		fd_set fdread ;
    		int ret ;
     
    		while(1)
    		{
     
     
    			FD_ZERO (&fdread) ;
    			FD_SET(s_ecoute, &fdread) ; 
     
    			if ((ret=select(0,&fdread,NULL,NULL,NULL))==-1)
    			{
    				perror("erreur select") ;
    				exit(-2) ;
     
    			}
    			else
    			printf("select reussi\n") ;					
     
    			if(FD_ISSET(s_ecoute, &fdread))
    			{
     
    				if ((fd=accept(s_ecoute, (struct sockaddr *)&client,&lg))==-1)
    				{
    					perror("erreur accept") ;
    					return(-1) ;
     
    				}	
    				else
    				{	
    					printf("accept reussi\n") ;
     
     
    					while(read(fd,&c,1)!=0)
    					write(1,&c,1) ;
    				}
    			}	
     
    		}
     
     
    	}
     
     
     
     
     
     
     
     
     
    	close(s_ecoute) ;
    	return 0 ;
    }

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    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 379
    Points : 41 575
    Points
    41 575
    Par défaut
    Pour l'instant, c'est pas mal. Le accept(), oui, il faut le mettre après le select() comme tu l'as fait.

    Par contre, le traitement du client accepté sera à changer pour un Tchat. Mais pour l'instant, corriger deux erreurs urgentes:
    * remplacer "read() != 0" par "read() > 0" (pour quitter aussi sur une erreur)
    * ajouter un close(fd) après la boucle while(read), sinon tu auras une fuite de socket.


    Ensuite, on va pouvoir envisager de modifier le traitement des clients pour transformer ton serveur en Tchat: Déjà, il te faudra mémoriser les sockets de tous les clients connectés, les ajouter au fd_set de lecture [Erreur], ainsi qu'à un nouveau fd_set "d'exception" (pour détecter quand il faut les fermer)[/Erreur].
    Alors, chaque fois qu'un client enverra un message, select() retournera et FD_ISSET() sera vrai pour son socket. Il faudra alors relayer le message à tous les clients connectés (y compris l'envoyeur: Cela permet à l'envoyeur de savoir quand le message a été traité).
    [Erreur]Et quand un client se déconnecte, FD_ISSET sera vrai pour son socket en exception, il faudra donc le fermer et le retirer de la liste des clients.[/Erreur]

    Edit: Skyrunner: Oui, dans l'état actuel, un seul client peut être connecté à la fois. Comme je viens de le dire, la prochaîne étape consistera à changer cela.

  3. #3
    Expert éminent sénior
    Avatar de Skyounet
    Homme Profil pro
    Software Engineer
    Inscrit en
    Mars 2005
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Software Engineer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 6 380
    Points : 13 380
    Points
    13 380
    Par défaut
    Il y a un leger probleme la, non?
    Imaginons qu'un client se connecte, aucun autre client ne pourra se connecté a cause du while(read())

    Si tu as besoin d'aide, je viens juste de finir un chat multi-client/multi-channel mais en C++.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 189
    Points : 60
    Points
    60
    Par défaut
    pour que plusieurs clients puisse se connecter il faut utiliser les threads je pense ... ou des fork() peut etre ? j'imagine qu'il faudra aussi que je fasse un tableau de struct sockaddr ?

    par contre là j'ai effectuée les modifications que tu m'as dites de faire et j'ai l'impression que le programme ne passe pas le select() ..

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    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 379
    Points : 41 575
    Points
    41 575
    Par défaut
    ne t'inquiète pas, avec select(), tu n'auras besoin ni de fork(), ni de threads. Par contre, il y a une petite erreur dans ce que j'ai dit: oublie tout sur le second fd_set, [Erreur]il n'est pas possible de détecter avec select() qu'un client s'est déconnecté[/Erreur].

    Simplement, il va falloir maintenir une liste (sans doute chaînée), pas forcément de structures sockaddr, mais au moins de sockets (plus de détails quand j'aurais mis de l'ordre dans ma tête).

    Edit1:
    * Lorsqu' un client est accepté, la connexion ne devra pas être fermée : Le socket du client sera simplement ajouté à la liste, puis on passe à l'itération suivante de la boucle while(1).
    * Au début de la boucle, entre le FD_ZERO et le select(), on ajoute tous les sockets de la liste dans le fd_set. Ainsi, le socket d'écoute et tous les sockets clients seront testés par select(). (le premier paramètre de select() devra être réglé en conséquence. Normalement, si on le règle à FD_SETSIZE, ça devrait marcher)
    * Après le select, on teste FD_ISSET pour chaque socket de la liste, et chaque fois que FD_ISSET est vrai, c'est que le client testé a envoyé un message : alors, on le renvoie à tous les clients. (Au passage, si send() renvoit une erreur, on ferme le socket concerné et on le retire de la liste)

  6. #6
    Expert éminent sénior
    Avatar de Skyounet
    Homme Profil pro
    Software Engineer
    Inscrit en
    Mars 2005
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Software Engineer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 6 380
    Points : 13 380
    Points
    13 380
    Par défaut
    Citation Envoyé par Médinoc
    Par contre, il y a une petite erreur dans ce que j'ai dit: oublie tout sur le second fd_set, il n'est pas possible de détecter avec select() qu'un client s'est déconnecté.
    Si, si lorsqu' un client de deconnecte (via Ctrl C par exemple) le select se declenche la socket du client est FD_ISSET et le read que tu va faire renvoi une valeur < 1

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    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 379
    Points : 41 575
    Points
    41 575
    Par défaut
    ah, j'ignorais. En tout cas, c'est une bonne nouvelle, puisque permettra un fonctionnement encore plus simple. (pas besoin de vérifier les envois aux autres clients pour les supprimer: on supprime juste le client courant si le read a renvoyé 0 (déconnexion normale) ou une valeur négative (erreur)...)

  8. #8
    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 : 67
    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 Re: utilisation de select() pour faire un Tchat
    Citation Envoyé par innosang
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    			if ((ret=select(0,&fdread,NULL,NULL,NULL))==-1)
    La valeur du premier paramètre de select() est incorrecte.

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 189
    Points : 60
    Points
    60
    Par défaut
    merci pour vos conseils je vais essayer de me débrouiller ... bon dimanche a tous


    quand vous me dites qu'il faut créer une liste de socket ... ce sont les fd que renvoient la fonction accept non ?

  10. #10
    Expert éminent sénior
    Avatar de Skyounet
    Homme Profil pro
    Software Engineer
    Inscrit en
    Mars 2005
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Software Engineer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 6 380
    Points : 13 380
    Points
    13 380
    Par défaut
    Citation Envoyé par innosang
    merci pour vos conseils je vais essayer de me débrouiller ... bon dimanche a tous


    quand vous me dites qu'il faut créer une liste de socket ... ce sont les fd que renvoient la fonction accept non ?
    Oui chaque fois qu'un client se connecte accept creer un nouveu fd, et ce fd tu l'insere dans ta liste (que tu va devoir implementer [c'est un bon exercice quand meme]) (vive quand meme la STL [C++] dmg quand meme).

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 189
    Points : 60
    Points
    60
    Par défaut
    bonjour tout le monde ... j'ai un peu avancé voici le code du serveur et celui de la structure de donnée ....

    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
    #include "fonc_socket.h"
     
     
    int main(char * argv[], int argc)
    {
    	int s_ecoute = createBindInetSocket(SOCK_STREAM,1234) ;
    	char c ;
    	struct sockaddr_in client;
    	struct hostent * h ;
     
    	int i ;
    	int lg = sizeof(struct sockaddr_in) ;
     
    	struct listeClients * l =listeNouv();
     
    	if (listen(s_ecoute,10)<0)
    	{
    		perror("erreur listen") ;
    		return(-2) ;
     
    	}
    	else
    	{	printf("listen réussi \n") ;
    		//printf("Serveur lancé ! En attente de messages ...\n") ;
     
     
    		fd_set fdread ;
    		int ret ;
     
    		while(1)
    		{
     
    			int fd ;
    			FD_ZERO (&fdread) ;	
    			FD_SET(s_ecoute, &fdread) ; 
    			struct listeClients * courant = listeNouv() ;
    			courant=l ;
    			while(courant!=NULL)
    			{
    				FD_SET(courant->s,&fdread) ;
    				//printf("%d\n", courant->s);
    				courant=courant->suivant ;
    			}
     
     
    			if ((ret=select(FD_SETSIZE,&fdread,NULL,NULL,NULL))==-1)
    			{
    				perror("erreur select") ;
    				exit(-2) ;
     
    			}
    			else
    			{
    			printf("select reussi\n") ;					
     
    				courant=l ;
    				while(courant!=NULL)
    				{
    					if(FD_ISSET(courant->s, &fdread))
    					{
     
     
     
    							printf("accept reussi\n") ;
     
    							while(read(courant->s,&c,1)>0)
    							write(1,&c,1) ;
     
     
     
    					}
    					courant=courant->suivant ;
     
    				}
     
    				if(FD_ISSET(s_ecoute, &fdread))
    				{
    					printf("FDiset\n") ;
     
    					if ((fd=accept(s_ecoute, (struct sockaddr *)&client,&lg))==-1)
    					{
    						perror("erreur accept") ;
    						return(-1) ;
     
    					}	
    					else
    					{	
    						printf("accept reussi\n") ;
    						l = ajoutListe(l,fd) ;
    						while(read(fd,&c,1)>0)
    						write(1,&c,1) ;
     
     
    					}
    				}
     
     
    			}
    		}
     
     
    	}
     
     
     
     
     
     
     
     
     
    	close(s_ecoute) ;
    	return 0 ;
    }

    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
    struct listeClients * listeNouv()
    {
    	struct listeClients * nouv = (struct listeClients *) malloc(sizeof (struct listeClients)) ;
    	nouv->suivant = NULL ;	
    	return nouv ;
    }
     
    struct listeClients * ajoutListe(struct listeClients * l,int socket)
    {
    	struct listeClients * n = listeNouv() ;
    	n->s=socket ;
    	struct listeClients * courant = l ;
     
    	while(courant->suivant!=NULL)
    	{
    		courant=courant->suivant ;
    	}
     
     
    	courant->suivant = n ;
     
    	return l ;
     
    }

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    struct listeClients 
    {	
     
    	int s;
    	struct listeClients * suivant ;
    };

    j'arrive toujours pas à ce que le serveur ecoute sur plusieurs clients

  12. #12
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    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 379
    Points : 41 575
    Points
    41 575
    Par défaut
    [ I ]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    struct listeClients * courant = listeNouv() ;
             courant=l ;
    Et hop, un joli leak de mémoire (début de la boucle while).
    Remplace simplement par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const struct listeClients *courant = l;
    (oui, on en profite pour le mettre en const, puisque quand tu lis la liste avec courant, tu ne la modifies pas.


    [ II ]
    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
                while(courant!=NULL)
                {
                   if(FD_ISSET(courant->s, &fdread))
                   {
     
     
     
                         printf("accept reussi\n") ;
     
                         while(read(courant->s,&c,1)>0)
                         write(1,&c,1) ;
     
     
     
                   }
                   courant=courant->suivant ;
     
                }
    Déjà, mauvais message: ce n'est pas "accept réussi" mais "un client connecté envoie quelque chose".
    Et ta boucle de read est erronée: Quand tu auras lu le dernier caractère envoyé, ton read() attendra indéfiniement.
    Mon conseil (en considérant qu'on garde la lecture carac par carac):
    1) En envoyant la chaîne, tu envoies le \0 avec.
    2)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while(read(courant->s, &c, 1)>0 && c!='\0')
    	putchar(c);
    putchar('\n');

    [ III ]
    Dans le "accept réussi" à la fin de la boucle, supprime la boucle read/write: Ici, tu ajustes seulement le nouveau client, on s'occupe de lui quand son tour vient.

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 189
    Points : 60
    Points
    60
    Par défaut
    oui en fait j'avais remarqué toutes les erreurs que tu viens de citer. Il y a eu transmission de pensées je crois

    par contre lorsqu'un client ecrit ... le serveur recois les caractères mais reste quand meme bloqué sur le read . en effet le
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("fin de lecture sur le socket :%d\n", courant->s)
    ne se fait pas

    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
    					if(FD_ISSET(courant->s, &fdread))
    					{
     
     
     
    							printf("lecture sur le socket : %d\n", courant->s) ;
     
    								while(read(courant->s, &c, 1)>0 && c!='\0')
       								putchar(c);
    								putchar('\n');
     
    							printf("fin de lecture sur le socket :%d\n", courant->s) ;	
     
     
     
    					}

  14. #14
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    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 379
    Points : 41 575
    Points
    41 575
    Par défaut
    le client envoit bien le \0 avec son message, comme je te l'ai conseillé? L'un ne marchera pas sans l'autre...

  15. #15
    Expert éminent sénior
    Avatar de Skyounet
    Homme Profil pro
    Software Engineer
    Inscrit en
    Mars 2005
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Software Engineer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 6 380
    Points : 13 380
    Points
    13 380
    Par défaut
    Envoyer et recevoir caractere par caractere c'est pas tres bon pour ton reseau ca.
    Je te conseille d'envoyer 1024 caracteres (par exemple) bien sur tu sera limité a 1024 caracteres, mais bon apres il faut voir si tu prefere saturé ton reseau ou etre limité a envoyé des messages de 1024 caractere.

  16. #16
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    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 379
    Points : 41 575
    Points
    41 575
    Par défaut
    L'envoi peut être fait d'un coup et la réception peut être faite par caractères sans trop de problème: C'est bufferisé.
    C'est dans l'autre sens, que ça coincerait.

  17. #17
    Nouveau membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Mars 2003
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2003
    Messages : 57
    Points : 27
    Points
    27
    Par défaut
    Je vois que je suis pas le seul à galérer sur le TP de RP.....

    Moi j'ai réussi plus ou moins avec select (le serveur recoit les messages de tous les clients), par contre je 'narrive pas à rediriger les messages vers les clients......

    J'avais d'abord fait un read avec un buffer de 256 octets (les clients recevaient seulement les quelques premiers octets puis plus rien....)
    A present je le fais caractere par caractere mais j'ai encore des soucis --> certains clients recoivent les messages d'autres non )

    Voici mon code :
    La structure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    typedef struct data{
      int libre;
      int desc;
      char buf[MAX_SIZE];
      char surnom[MAX_SURNOM];
    }*DataUser;
    Les fonctions de lecture/ecriture sur les clients
    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
    void readOnUser(fd_set *readfds, DataUser connectes)
    {
      int i, lu;
      char buf[MAX_SIZE+MAX_SURNOM+4];
      for(i=0;i<MAX_USER;i++)
      {
        if(!connectes[i].libre)
        {
          if(FD_ISSET(connectes[i].desc,readfds))
          {
            lu = READ(connectes[i].desc, connectes[i].buf, MAX_SIZE);
            connectes[i].buf[lu] = '\0';
            if(lu>0)    
            {
              sprintf(buf,"%s: %s", connectes[i].surnom,connectes[i].buf);                             
              printf("%s",buf);
              sendToUser(i,buf,connectes);
            }
          }
        }
      }
    }
     
    void sendToUser(int sender, char *msg, DataUser connectes)     
    {
      int j;
      for(j=0;j<MAX_USER;j++)
      {
        if(!connectes[j].libre)
        {      
          if(connectes[j].desc != connectes[sender].desc)
          {
            strcpy(connectes[j].buf,msg);
            WRITE(connectes[j].desc,connectes[j].buf,sizeof(connectes[j].buf));
          }
        }
      }
    }
    Et la fonction de lecture chez le client :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      if(FD_ISSET(fd,&readfds2))
            {                
              while(read(fd,&c,1) !='\0')          
                printf("%c",c);
            }

    Voila désolé pour le gros bout de code.....

    Si qq1 pouvait m'aider à comprendre ce qui cloche.....

  18. #18
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    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 379
    Points : 41 575
    Points
    41 575
    Par défaut
    euh, pour l'instant, on va éviter de mélanger les deux codes. Il faudra que tu attendes, car on n'en avait pas encore fini.
    D'ailleurs, il est possible que tes questions trouvent leur réponse bientôt.

    innosang -> Dis-moi si ça marche après s'être assuré que le client envoie bien le zero terminal.
    (il peut envoyer tout simplement comme ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char szMessage[80];
    fgets(szMessage, 80, stdin);
    send(fd, szMessage, stdlen(szMessage)+1, 0);
    )

    Si ça marche, on va pouvoir passer à l'étape suivante: Permettre que le client se déconnecte (on fera ça en rajoutant 2-3 petites choses dans la boucle du recv)

  19. #19
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 189
    Points : 60
    Points
    60
    Par défaut
    oui l'envoi fonctionne en fait mais j'ai un probleme avec les valeurs que me renvois le accept ... en fait j'affiche les descripteurs de fichier a chaque fois qu'un nouveau client se connecte et ça me donne ...
    pour un client : 0
    pour deux clients : 0 4
    pour trois clients : 0 4 5

    est ce qu'un descripteur de fichier peut prendre 0 comme valeur ? ca correspond a l'entrée standard non ?

  20. #20
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 189
    Points : 60
    Points
    60
    Par défaut
    ah bein je sais pas ce que j'ai changé mais j'arrive à lire sur plusieurs clients ... bizarre :o

Discussions similaires

  1. Utiliser UPDATE + SELECT pour faire un cache FIFO
    Par WeeJay dans le forum Langage SQL
    Réponses: 5
    Dernier message: 19/05/2008, 12h10
  2. utiliser un Formulaire pour faire un état
    Par girl257 dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 19/09/2007, 19h13
  3. utilisation du TChart pour faire des graphiques
    Par tchimou dans le forum Bases de données
    Réponses: 2
    Dernier message: 30/04/2007, 14h59
  4. utiliser données texte pour faire des calculs
    Par sarah67 dans le forum Access
    Réponses: 20
    Dernier message: 06/02/2006, 14h09

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