Bonjour,

Toujours dans l'apprentissage des sockets, j'ai essayé de mettre au point un chat (un serveur et multi-client). Les clients ont l'air de pouvoir communiqué jusqu'au serveur (je n'ai testé qu'avec un seul client et ça fonctionne). En revanche je ne parviens à renvoyer les messages du serveur vers les clients...
Ce qui est gênant pour un chat.

Pour mettre en place la liste des clients, j'ai pour le moment utilisé une liste simplement chaînée qui deviendra doublement chaînée à l'avenir (plus simple pour gérer les déconnexions).

Le fonctionnement du serveur :
J'initialise le socket de connexion des clients, j'utilise select pour gérer les différents descripteurs de fichier. À partir du moment où quelque chose se passe sur le socket de connexion, j'accepte le nouveau client et je l'ajoute à la liste. S'il ne se passe rien sur celui-ci je boucle sur les sockets clients pour voir si l'un d'eux essaye d'écrire... Pour le moment le serveur renvoit à tous les clients sans exceptions, c'est juste pour les tests.

Le fonctionnement du client:
J'initialise le socket qui permet de se connecter au serveur, je me connecte au serveur. J'utilise select pour les différents descripteurs de fichiers (ici STDIN_FILENO et sock). S'il se passe quelque chose sur STDIN_FILENO, le client est en train d'écrire. Sinon s'il se passe quelque chose sur sock c'est que le serveur est en entrain d'expédier un message.

Or le problème est là le client ne parvient pas à recevoir le message du serveur qui est pourtant bien envoyé (send renvoit le bon nombre d'octets).

Je vous poste mon code : (pour informations je suis sous linux)

Code client :

client.h
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
ifndef CONNEXION_H
#define CONNEXION_H
 
#define TAILLE_TAMPON 256
 
#define IP "192.168.0.2"
#define PORT 4000
 
#endif
client.c

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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/times.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
 
#include "connexion.h"
 
int
socket_creer(void)
{
    int sock;
 
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	return -1;
 
    return sock;
}
 
int
socket_connecter(int sock, char* ip, int port)
{
    struct sockaddr_in serveur;
    socklen_t taille = sizeof(struct sockaddr);
 
    serveur.sin_family = AF_INET;
    serveur.sin_addr.s_addr = inet_addr(ip);
    serveur.sin_port = htons(port);
 
    if (connect(sock, (struct sockaddr*) &serveur, taille) == -1)
	return -1;
 
    return 1;
}
 
int
main(void)
{
    int sock;
    int taille;
    int continuer = 1;
    char tampon[TAILLE_TAMPON];
    fd_set rfds;
 
    if ((sock = socket_creer()) == -1)
	return -1;
 
    if (socket_connecter(sock, IP, PORT) == -1)
	return -1;
 
    FD_ZERO(&rfds);
    FD_SET(STDIN_FILENO, &rfds);
    FD_SET(sock, &rfds);
 
    while (continuer)
    {
	select(sock + 1, &rfds, NULL, NULL, NULL);
	if (FD_ISSET(STDIN_FILENO, &rfds))
	{
	    fgets(tampon, TAILLE_TAMPON - 1, stdin);
	    if ((taille = send(sock, tampon, strlen(tampon), 0)) == -1)	
	    {
		return -1;
	    }
	}
	else if (FD_ISSET(sock, &rfds))
	{
	    printf("Réception !\n");
	    if ((taille = recv(sock, tampon, TAILLE_TAMPON - 1, 0)) == -1)
	    {
		return -1;
	    }
	    else
	    {
		tampon[taille - 1] = '\0';
		printf("%s\n", tampon);
	    }
	}
    }
 
    close(sock);
 
    return 0;
}
Ici le code complet sur serveur, le fichier liste_clients.c sert à la gestion des listes.

serveur.c

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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stddef.h>
 
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/times.h>
#include <arpa/inet.h>
#include <unistd.h>
 
#include "connexion.h"
#include "liste_clients.h"
 
int
socket_creer(void)
{
    int sock;
 
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	return -1;
 
    return sock;
}
 
int
socket_configurer(int sock, int port)
{
    struct sockaddr_in serveur;
    size_t taille = sizeof(struct sockaddr_in);
 
    serveur.sin_family = AF_INET;
    serveur.sin_port = htons(port);
    serveur.sin_addr.s_addr = INADDR_ANY;
    bzero(&(serveur.sin_zero), 8);
 
    if (bind(sock, (struct sockaddr*) &serveur, taille) == -1)
	return -1;
 
    return 1;
}
 
int
socket_ecouter(int sock, int clients)
{
    if (listen(sock, clients) == -1)
	return -1;
 
    return 1;
}
 
int
client_ajouter(Clients* clients, int sock, fd_set* rfds)
{
    int sock_client;
    struct sockaddr_in client;
    socklen_t taille_client = sizeof(struct sockaddr);
 
    sock_client = accept(sock, (struct sockaddr*) &client, &taille_client);
    if (sock_client == -1)
	return -1;
 
    lc_ajouter_en_tete(clients, sock_client);
    FD_SET(sock_client, rfds);
 
    return sock_client;
}
 
void
traiter(Clients* liste, int sock, fd_set* rfds, char* tampon, int taille)
{
    Client* client;
 
    tampon[taille - 1] = '\0';
 
    if (strcmp("/quitter", tampon) == 0)
    {
	client = lc_extraire(liste, sock);
	lc_supprimer(client);	
	FD_CLR(sock, rfds);
    }
    else
    {
	printf("%s\n", tampon);
	client = *liste;
	while (client != NULL)
	{
	    printf("Envoi !\n");
	    printf("%ld\n", send(client->sock, tampon, strlen(tampon), 0));
	    client = client->suivant;
	}
    }
}
 
int
application(int sock)
{
    int continuer = 1;
    int taille;
    int max = sock;
    int erreur;
    Clients clients = NULL;
    Clients index;
    char tampon[TAILLE_TAMPON];
    fd_set rfds;
 
    FD_ZERO(&rfds);
    FD_SET(sock, &rfds);
 
    while (continuer)
    {
	select(max + 1, &rfds, NULL, NULL, NULL);
	if (FD_ISSET(sock, &rfds))
	{
	    erreur = client_ajouter(&clients, sock, &rfds);
	    if (erreur == -1)
		return -1;
	    max = lc_maximum_socket(clients);
	}
	else 
	{
	    index = clients;
	    while (index != NULL)
	    {
		if (FD_ISSET(index->sock, &rfds))
		{
		    if ((taille = recv(index->sock, tampon, TAILLE_TAMPON - 1,
				       0)) == -1)
			return -1;
		    traiter(&clients, index->sock, &rfds, tampon, taille);
		    max = lc_maximum_socket(clients);
		}
		index = index->suivant;
	    }
	}
    }
 
    return 1;
}
 
int
main(void)
{
    int sock;
 
    if ((sock = socket_creer()) == -1)
	return -1;
 
    printf("socket n°%d\n", sock);
 
    if (socket_configurer(sock, PORT) == -1)
	return -1;
 
    if (socket_ecouter(sock, NB_CLIENTS) == -1)
	return -1;
 
    printf("Initialisation correcte\n");
 
    application(sock);
 
    close(sock);
 
    printf("Fermeture du socket\n");
 
    return 0;
}
serveur.h

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
#ifndef CONNEXION_H
#define CONNEXION_H
 
#define TAILLE_TAMPON 256
 
#define PORT 4000
#define NB_CLIENTS 10
 
#endif
Et voici le code des fichiers qui gèrent les listes :

liste.c

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
#include <stdio.h>
#include <stdlib.h>
 
#include "liste_clients.h"
 
Client*
lc_creer(int sock)
{
    Client* client;
 
    if ((client = malloc(sizeof(Client))) == NULL)
	return NULL;
 
    client->sock = sock;
    client->suivant = NULL;
 
    return client;
}
 
Client*
lc_ajouter_en_tete(Clients* liste, int sock)
{
    Client* client;
 
    if ((client = lc_creer(sock)) == NULL)
	return NULL;
 
    if (*liste == NULL)
	*liste = client;
    else
    {
	client->suivant = *liste;
	*liste = client;
    }
 
    return client;
}
 
Client*
lc_extraire(Clients* liste, int sock)
{
    Client* index;
    Client* tmp;
 
    if (*liste == NULL)
	return NULL;
 
    if ((*liste)->sock == sock)
    {
	index = *liste;
	*liste = (*liste)->suivant;
	return index;
    }
    else
    {
	index = *liste;
	while (index != NULL && index->suivant != NULL)
	{
	    if (index->suivant->sock == sock)
	    {
		tmp = index->suivant;
		index->suivant = index->suivant->suivant;
		return tmp;
	    }
	    index = index->suivant;
	}
    }
 
    return NULL;
}
 
void
lc_supprimer(Client* client)
{
    free(client);
}
 
void
lc_supprimer_tous(Clients* liste)
{
    Client* tmp;
 
    if (*liste == NULL)
	return;
 
    while (*liste != NULL)
    {
	tmp = *liste;
	*liste = (*liste)->suivant;
	free(tmp);
    }
}
 
int
lc_maximum_socket(Clients liste)
{
    int max;
 
    if (liste == NULL)
	return -1;
 
    while (liste != NULL)
    {
	if (liste->sock > max)
	    max = liste->sock;
	liste = liste->suivant;
    }
 
    return max;
}
 
void
lc_ecrire(Clients liste)
{
    if (liste == NULL)
	printf("Liste vide !\n");
 
    while (liste != NULL)
    {
	printf("%d\n", liste->sock);
	liste = liste->suivant;
    }
}
liste.h

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
#ifndef LISTE_CLIENTS_H
#define LISTE_CLIENTS_H
 
typedef struct client
{
    int sock;
    struct client* suivant;
} Client, *Clients;
 
Client*
lc_creer(int sock);
 
Client*
lc_ajouter_en_tete(Clients* liste, int sock);
 
Client*
lc_extraire(Clients* liste, int sock);
 
void
lc_supprimer(Client* client);
 
void
lc_supprimer_tous(Clients* liste);
 
int
lc_maximum_socket(Clients liste);
 
void
lc_ecrire(Clients liste);
 
#endif
Voilà si quelque chose n'est pas clair, j'apporterai des précisions ;-)

Merci à vous pour votre aide.

Bye.