Bonjour tout le monde,

J'ai un petit soucis avec des threads en C.

Je dois développer un petit chat, en local, et utiliser des threads.

J'ai donc deux executables, un serveur, qui se lance comme démon et qui reçoit tous les messages des différents utilisateurs dans une file de message qu'il créé lui-même et qui les renvoit dans chaque file propre à un client.
Comme ça, tous les clients reçoivent les messages de tout le monde.
De ce côté-là, je n'ai pas de soucis.
Pour l'instant, pas de thread à gérer, j'ai une boucle infinie dans le serveur qui lui permet d'être toujours en attente de message dans sa file et qui les traitent quand il en reçoit !

Pour mon client, il doit d'abord récupérer la file du serveur, ensuite il se créé sa propre file et puis il envoit son pseudo et son file_id au serveur, qui vérifie le pseudo et lui renvoit un message sur la file du client pour l'autoriser à entrer ou non.
Après, je lance 2 threads. Un qui est en attente de messages sur sa file (et qui doit recevoir tous les messages des autres clients) et un qui permet d'envoyer des messages et qui est donc dans l'attente de saisie d'une chaine au clavier.

Seulement, si je créé le thread d'envoi en premier, je peux envoyer des messages mais n'en reçois pas !
Alors que si je fais l'inverse, je peux en recevoir mais pas en créer ...

En fait, les threads ne semblent pas s'exécuter en parallèle, alors que c'est quand même leur but, si je ne me trompe pas ...

Voilà, si quelqu'un avait une idée ...

Je vous remercie par avance et vous mets le code de mon chat.c (qui correspond au 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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
#include "file.h"
#include <errno.h>
 
/** Definition des variables globales : **/
static char* PSEUDO;
static int MSQID_SERV;
static int MSQID_RCV;
static key_t cle_serv;
static key_t cle_client;
 
/* Declaration de la fenetre */
WINDOW *f_haut, *f_bas;
 
 
 
WINDOW *creation_fenetre(int n, int d, char *t){
 
	WINDOW *cadre;
 
	WINDOW *w;
 
 
 
	cadre = newwin(n, COLS, d, 0);
 
	box(cadre, 0,0);
 
	mvwprintw(cadre,0,COLS/2-strlen(t)/2,t);
 
 
 
	wrefresh(cadre);
 
 
 
	w = newwin(n-2, COLS-2, d+1, 1);
 
	idlok(w, TRUE);
 
	scrollok(w, TRUE);
 
	wclear(w);
 
 
 
	wrefresh(w);
 
 
 
	return w;
 
}
 
 
 
 
void connexion(){
	message *mmsg;
	mmsg = malloc(sizeof(struct message));
	(*mmsg).mtype = 1;
	strcpy((*mmsg).mtext, ">> ");
	strcat((*mmsg).mtext, PSEUDO);
	strcat((*mmsg).mtext, TXT_CONNEXION_AUTRE);
	strcpy((*mmsg).pseudo, PSEUDO);
	(*mmsg).msqid = MSQID_RCV;
	msgsnd(MSQID_SERV, mmsg, sizeof(struct message), MSG_NOERROR);
	return;
}
 
 
/* Fonction qui envoie un message vers le serveur */
void envoi_msg(char* msg){
	message *mmsg;
	mmsg = malloc(sizeof(struct message));
	(*mmsg).mtype = 10;
	strcpy((*mmsg).mtext, PSEUDO);
	strcat((*mmsg).mtext, DIRE);
	strcat((*mmsg).mtext, msg);
	strcpy((*mmsg).pseudo,PSEUDO);
	(*mmsg).msqid = MSQID_RCV;
	msgsnd(MSQID_SERV, mmsg, sizeof(message), MSG_NOERROR);
	return;
}
 
 
 
void deconnexion(){
	message *mmsg;
	mmsg = malloc(sizeof(struct message));
	(*mmsg).mtype = 3;
	strcpy((*mmsg).mtext, "<< ");
	strcat((*mmsg).mtext, PSEUDO);
	strcat((*mmsg).mtext, TXT_DECONNEXION_AUTRE);
	strcpy((*mmsg).pseudo,PSEUDO);
	(*mmsg).msqid = MSQID_RCV;
	msgsnd(MSQID_SERV, mmsg, sizeof(message), MSG_NOERROR);
	return;
}
 
 
/* Fonction permettant l'envoi des messages */
void * envoi_messages(){
	message *mmsg;
	mmsg = malloc(sizeof(struct message));
	char *msg;
	msg = malloc(sizeof(char)*255);
	wgetstr(f_bas, msg);
	while(strcmp(TXT_QUIT,msg) != 0){
		(*mmsg).mtype = 4;
		strcpy((*mmsg).mtext,msg);
		/* Envoi du message dans la file */
		envoi_msg(msg);
		werase(f_bas);
		wgetstr(f_bas, msg);
	}
	/* Deconnexion de l'utilisateur ! */
	deconnexion();
	pthread_exit(0);
	return 0;
}
 
 
/* Fonction permettant la reception des messages */
void * reception_messages(){
	message *msgp;
	msgp = malloc(sizeof(struct message));
	int msgsz = sizeof(struct message);
	while(1){
		msgrcv(MSQID_RCV,msgp,msgsz,0,0);
		switch((*msgp).mtype){
			case 4:
				waddstr(f_haut,"Message recu : ");
				waddstr(f_haut,(*msgp).mtext);
				waddstr(f_haut,"\n");
				wrefresh(f_haut);
				break;
			default:
				waddstr(f_haut,"ICI \n");
				wrefresh(f_haut);
				break;
		}
	}
	pthread_exit(0);
	return 0;
}
 
 
 
 
/* Fonction principale du programme chat */
int main(int argc, char* argv[]){
	struct msqid_ds *stat;
	stat = malloc(sizeof(struct msqid_ds));
	message *mmsg;
	mmsg = malloc(sizeof(struct message));
	PSEUDO = malloc(sizeof(char)*255);
	int i;
 
	/* Test des parametres */
	if(argc != 3){
		printf("%s",USAGE_CHAT);
		return -1;
	}
 
	if(strcmp(argv[1], "-p") != 0){
		return -1;
	}
 
	/* Recuperation du pseudo dans la variable globale PSEUDO */
	strcpy(PSEUDO, argv[2]);
 
	/* Creation de la cle du serveur */
	cle_serv = ftok(KEY_FILE,KEY_ID_SERV);
 
	/* Recuperation de l'identificateur de la file de messages du serveur */
	MSQID_SERV = msgget(cle_serv, IPC_STAT);
 
	printf("File serveur : %i\n",MSQID_SERV);
	/* Si aucune file de message n'est trouvee, on quitte */
	if(MSQID_SERV == -1){
		printf("Aucun serveur trouve !!\n");
		exit(1);
	}
 
	/* On cree une file de messages du client (unique a chaque client) */
	i = 1;
	cle_client = ftok(KEY_FILE,i);
	MSQID_RCV = msgget(cle_client, IPC_STAT);
	while(MSQID_RCV != -1){
		i++;
		cle_client = ftok(KEY_FILE,i);
		MSQID_RCV = msgget(cle_client, IPC_STAT);
	}
	MSQID_RCV = msgget(cle_client, IPC_CREAT | 0666);
	if(MSQID_RCV == -1){
		printf("Erreur lors de la creation de la file du client !\n");
		printf("Errno : %i \n",errno);
		exit(0);
	}
	printf("Ma file est : %i\n", MSQID_RCV);
 
	/* Si on a trouve la file de messages du serveur, on etablit la connexion */
	connexion();
 
 
	/* Attente du message du serveur pour confirmation de connexion */
	msgrcv(MSQID_RCV,mmsg,sizeof(struct message),0,3);
	if((*mmsg).msqid < 0){
		printf("Le pseudo '%s' est deja utilisé !\nVeuillez en essayer un autre ou tentez de vous reconnecter plus tard ...\n",(*mmsg).pseudo);
		exit(0);
	}
 
 
	initscr();
 
	noecho();
 
	cbreak();
 
 
 
	f_haut = creation_fenetre(18,0,"MESSAGES : ");
 
	f_bas = creation_fenetre(6,18,"ENVOI DE MESSAGE : ");
 
 
	echo();
 
	/* Declaration des threads */
	pthread_t my_thread_snd;
	pthread_t my_thread_rcv;
 
	/* Creation du thread pour l'envoi des messages */
	if(pthread_create(&my_thread_snd, NULL, envoi_messages, NULL) < 0){
		printf("pthread_create erreur for thread 1 \n");
		exit(1);
	}
 
 
	/* Creation du thread pour la reception des messages */
	if(pthread_create(&my_thread_rcv, NULL, reception_messages, NULL) < 0){
		printf("pthread_create erreur for thread 1 \n");
		exit(1);
	}
 
	pthread_join(my_thread_rcv, NULL);
	pthread_join(my_thread_snd, NULL);
 
 
 
	endwin();
	return 0;
}