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 :

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;
 
}
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
#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;
}
Voilà, je vous remercie si vous pouvez m'aider.