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
client.c
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
Ici le code complet sur serveur, le fichier liste_clients.c sert à la gestion des listes.
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; }
serveur.c
serveur.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
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; }
Et voici le code des fichiers qui gèrent les listes :
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
liste.c
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
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; } }
Voilà si quelque chose n'est pas clair, j'apporterai des précisions ;-)
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
Merci à vous pour votre aide.
Bye.
Partager