Bonjour,
Je ne suis pas particulièrement bon en C, et je dois faire un programme de talk entre un serveur et plusieurs clients. Le principe est le suivant : les clients se connectent au serveur, et lorsqu'un client envoie un message au serveur, ce-dernier est renvoyé à tous les autres clients. C'est ce dernier point qui ne marche pas, soit le message est mal traité à la réception, soit il n'est pas envoyé au bon endroit, et je ne comprends pas pourquoi.
Je précise que je travaille sous linux.
Voici le code du serveur :
Et celui du client :
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 #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <inttypes.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define BUF_SIZE 1024 struct info_client { struct sockaddr_in addr; int socket; }; int main(int argc, char ** argv) { int sockfd1; // descripteurs de socket int temp_sock; // socket temporaire char buf[BUF_SIZE]; // espace necessaire pour stocker le message recu memset(buf, 0, BUF_SIZE); struct info_client tab_clients[5]; // tableaux de clients int nb_clients = 0; // nombres de clients dans le tableau struct sockaddr_in my_addr; // structure d'adresse qui contiendra les param reseaux du recepteur struct sockaddr_in addr_client; // structure d'adresse qui contiendra les param reseaux de l'expediteur fd_set readfds; fd_set readfds2; int ndfs; int code_retour; // taille d'une structure sockaddr_in utile pour la fonction recvfrom socklen_t sin_size = sizeof(struct sockaddr_in); // verification du nombre d'arguments sur la ligne de commande if(argc != 2) { printf("Usage: %s port_local\n", argv[0]); exit(0); } // creation de la socket sockfd1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // initialisation de la structure d'adresse du serveur (pg local) // famille d'adresse my_addr.sin_family = AF_INET; // recuperation du port du serveur my_addr.sin_port = htons(atoi(argv[1])); // adresse IPv4 du serveur //inet_aton(..., &(my_addr.sin_addr)); my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // association de la socket et des param reseaux du serveur if(bind(sockfd1, (const struct sockaddr *)&my_addr, sizeof(my_addr)) != 0) { perror("Erreur lors de l'appel a bind -> "); exit(1); } FD_ZERO(&readfds); FD_SET(sockfd1, &readfds); ndfs = sockfd1 + 1; while (1) { printf("Attente de connexion\n"); if(listen(sockfd1, 5) != 0) { perror("Erreur lors de l'appel a listen -> "); exit(2); } readfds2 = readfds; code_retour = select(ndfs, &readfds2, 0, 0, 0); printf("Select\n"); if(code_retour == -1) { /*traitement de l'erreur*/ perror("select"); } else { if(FD_ISSET(sockfd1, &readfds2)) { // on accepte les connexions entrantes if((temp_sock = accept(sockfd1, (struct sockaddr *)&addr_client, &sin_size)) == -1) { perror("Erreur lors de accept -> "); exit(3); } struct info_client client; client.addr = addr_client; client.socket = temp_sock; tab_clients[nb_clients] = client; FD_SET(tab_clients[nb_clients].socket, &readfds); if(sockfd1 > tab_clients[nb_clients].socket) { ndfs = sockfd1 + 1; } else { ndfs = tab_clients[nb_clients].socket + 1; } nb_clients++; printf("Connexion etablie avec le client %d\n", nb_clients); } int i = 0; while(i < 4) { if(FD_ISSET(tab_clients[i].socket, &readfds2)) { // reception de la chaine de caracteres if(read(tab_clients[i].socket, buf, BUF_SIZE, 0) == -1) { perror("Erreur lors de la reception -> "); exit(4); } printf("La chaine recue est: %s\n",buf); int j = 0; while(j < 5) { if(j != i) { write(tab_clients[j], buf, strlen(buf), 0); printf("Message envoyé au client %d\n", j); } j++; } } i++; } } } // fermeture des sockets int i = 0; while (i < 4) { close(tab_clients[i].socket); i++; } close(sockfd1); return 0; }
Voilà, je vous remercie si vous pouvez m'aider.
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 #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <inttypes.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #define BUF_SIZE 1024 int main(int argc, char **argv) { int sockfd; // socket d'envoi au serveur int sockfd1; // socket d'écoute int entree_standard = 0; // descripteur de l'entrée standard struct sockaddr_in serveur; // structure d'adresse qui contiendra les param reseaux du serveur struct sockaddr_in my_addr; // structure d'adresse qui contiendra les param reseaux du recepteur // taille d'une structure sockaddr_in utile pour la fonction recvfrom socklen_t sin_size = sizeof(struct sockaddr_in); char buf[BUF_SIZE]; // espace necessaire pour stocker le message recu memset(buf, 0, BUF_SIZE); fd_set readfds; fd_set readfds2; int ndfs; int code_retour; // verification du nombre d'arguments sur la ligne de commande if(argc != 3) { printf("Usage: %s @serveur port_serveur", argv[0]); exit(-1); } // creation de la socket sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); sockfd1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // initialisation de la structure d'adresse du serveur : // famille d'adresse serveur.sin_family = AF_INET; my_addr.sin_family = AF_INET; // recuperation de l'adresse IPv4 du serveur inet_aton(argv[1], &(serveur.sin_addr)); // recuperation du port du serveur serveur.sin_port = htons(atoi(argv[2])); // adresse IPv4 du serveur //inet_aton(..., &(my_addr.sin_addr)); my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // association de la socket et des param reseaux du serveur /*if(bind(sockfd1, (const struct sockaddr *)&my_addr, sizeof(my_addr)) != 0) { perror("Erreur lors de l'appel a bind -> "); exit(1); }*/ printf("Tentative de connexion\n"); // tentative de connexion if(connect(sockfd, (struct sockaddr*)&serveur, sizeof(serveur)) == -1) { perror("Erreur de connexion -> "); exit(2); } printf("Connexion etablie\n"); // attente de réponse du serveur FD_ZERO(&readfds); FD_SET(sockfd1, &readfds); FD_SET(entree_standard, &readfds); if(sockfd1 > entree_standard) { ndfs = sockfd1 + 1; } else { ndfs = entree_standard + 1; } while (1) { if(listen(sockfd1, 1) != 0) { perror("Erreur lors de l'appel a listen -> "); exit(2); } readfds2 = readfds; code_retour = select(ndfs, &readfds2, 0, 0, 0); printf("Select\n"); if(code_retour == -1) { /*traitement de l'erreur*/ perror("select"); } else { if(FD_ISSET(sockfd1, &readfds2)) { printf("Message reçu.\n"); if(read(sockfd1, buf, BUF_SIZE, 0) == -1) { perror("Erreur lors de la reception -> "); exit(4); } printf("La chaine recue est: %s\n",buf); } if(FD_ISSET(entree_standard, &readfds2)) { //lecture de la chaine de caractère read(entree_standard, buf, BUF_SIZE, 0); char * message = strcat(buf, "\0"); // envoi de la chaine if(send(sockfd, message, strlen(message), 0) == -1) { perror("Erreur lors de l'appel a send -> "); exit(3); } printf("Message envoyé\n"); } } } // fermeture de la socket close(sockfd); printf("deconnexion\n"); return 0; }
Partager