Bonjour
J'essaie de réaliser une communication entre deux processus avec un pipe nommé.
Je suis électronicien à la base, et ces mécanisme me sont connus car utilisé avec de petits OS embarqués, mais là l'implémentation windows me pose des PB.
Le serveur crée le pipe nommé. Le client s'y connecte. J'ai la preuve que les deux sont connectés. Puis lorsqu'ils sont connectés chacun crée de son côté un thread qui va gérer la communication.
Pour les tests le client écrit dans le pipe et serveur récupère et affiche.
Du côté serveur, dans le thread de comm je fais une lecture bloquante et du côté client dans le processus principal je fais une écriture dans le pipe.
Les applications sont lancées chacune de leur côté dans une console propre.
Je lance le serveur, il me dit qu'il a réussi à créer un pipe, et qu'il attend que le client se connecte au pipe.
Je lance le client, dont la première action est de se connecter au pipe. Et je vois côté serveur que la connection est un succès.
Maintenant serveur et client créent chacun de leur côté leur thread de comm, et il ya confirmation de la création.
Le problème est que client reste bloqué sur l'écriture dans le pipe alors que celui-ci est vide (enfin en principe). Et là j'avoue que je n'arrive pas à comprendre.
Par avance merci pour votre aide
Voici le code du serveur.
Et le code 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
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 // Il s'agit du fichier projet principal pour le projet d'application VC++ // généré en utilisant un Assistant Application. #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <windows.h> #using <mscorlib.dll> using namespace System; /*###################################################################################*/ /* CONSTANTES #######################################################################*/ /*###################################################################################*/ #define BUFSIZE 128 #define PIPE_TIMEOUT 1000 /*###################################################################################*/ /* FONCTIONS ########################################################################*/ /*###################################################################################*/ /*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/ VOID myErrExit (LPTSTR lpszMessage) { LPVOID lpMsgBuf; int err; err=GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); fprintf(stderr,"Serveur Err:%d Msg:%s\n",err,lpMsgBuf); LocalFree(lpMsgBuf); fprintf(stderr, "Serveur: %s\n", lpszMessage); getchar(); ExitProcess(-1); } /*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/ VOID ThreadCommunication(LPVOID lpvParam) { CHAR msgDeVision[BUFSIZE]; DWORD nbLus,nbRestants,nbTotaux; BOOL lecReussie=1; int nbL=0; HANDLE hPipe; hPipe = (HANDLE) lpvParam; // Cast pour récupérer le handle du pipe // Synchronisation avec le client /*fprintf(stderr,"Entrée dans le thread comm avec handle n %d\n",hPipe); PeekNamedPipe( hPipe, msgDeVision, BUFSIZE, &nbLus, &nbTotaux, &nbRestants ); fprintf(stderr,"avant %d %d %d\n",nbLus,nbTotaux,nbRestants); if(nbLus>0) { msgDeVision[nbLus+1]='\0'; fprintf(stderr,"msg= %s\n",msgDeVision); } */ FlushFileBuffers(hPipe); // vide le pipe pour le client /* PeekNamedPipe( hPipe, msgDeVision, BUFSIZE, &nbLus, &nbTotaux, &nbRestants ); fprintf(stderr,"après %d %d %d\n",nbLus,nbTotaux,nbRestants);*/ do { /*PeekNamedPipe( hPipe, msgDeVision, BUFSIZE, &nbLus, &nbTotaux, &nbRestants ); if(nbLus>0) { fprintf(stderr,"Bcl[%d] %d %d %d\n",nbL,nbLus,nbTotaux,nbRestants);*/ lecReussie=ReadFile( hPipe, msgDeVision, BUFSIZE, &nbLus, NULL); if(lecReussie) { msgDeVision[nbLus+1]='\0'; fprintf(stderr,"SERVEUR: recu[%d] lus=%d :%s\n",nbL,nbLus,msgDeVision); nbL++; } else { LPVOID lpMsgBuf; int err; fprintf(stderr,"SERVEUR: Erreur reception\n"); err=GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); fprintf(stderr,"Serveur Err:%d Msg:%s\n",err,lpMsgBuf); LocalFree(lpMsgBuf); } /*} else fprintf(stderr,"Bcl[%d] rien\n",nbL);*/ }while((nbL<5000)&&(lecReussie!=0)); fprintf(stderr,"SERVEUR sortie car "); if(lecReussie==0) { fprintf(stderr,"Quitte le thread comm, erreur lect\n"); ExitThread(-1); } else { fprintf(stderr,"Quitte le thread comm Nb>lim\n"); ExitThread(0); } } /*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/ int _tmain() { BOOL processClient=false; BOOL pipeConnecte=false; BOOL erreurPipe=false; DWORD dwThreadId; // L'identifiant du thread HANDLE hPipe, // Handle du pipe hThread; // Handle du thread DWORD sortieThread; LPTSTR lpszPipename = "\\\\.\\pipe\\mynamedpipe"; // Nom du pipe STARTUPINFO startupInfo; PROCESS_INFORMATION processInfo; // Création d'un pipe nommé Console::Write(S"SERVEUR: Creation du pipe nomme"); Console::WriteLine(lpszPipename); hPipe = CreateNamedPipe( lpszPipename, // Nom du pipe PIPE_ACCESS_DUPLEX, // Accès en lecture/ecriture PIPE_TYPE_MESSAGE | // message type pipe PIPE_READMODE_MESSAGE | // message-read mode PIPE_WAIT, // blocking mode PIPE_UNLIMITED_INSTANCES, // max. instances BUFSIZE, // output buffer size BUFSIZE, // input buffer size PIPE_TIMEOUT, // client time-out NULL); // no security attribute if (hPipe == INVALID_HANDLE_VALUE) myErrExit("Erreur dans la creation du Pipe cote serveur"); Console::Write(S"SERVEUR: Pipe nomme n°"); Console::Write((int)hPipe); Console::WriteLine(S" cree avec succes, lancement du processus fils/client"); // Lancement du processus client // Le processus client s'appelle client et est situé dans le docciser Comm/Client /*char cmd[15]; sprintf(cmd," %d",hPipe); processClient=CreateProcess("C:\\WINNT\\system32\\CMD.exe ", cmd, // Ligne de commande NULL, // Attributs de sécurité NULL, // TRUE, // les handles sont hérités 0, // flags NULL, // Utilise l'environnement du parent NULL, // Utilise le dossier parent &startupInfo, // &processInfo // ); if(!processClient) { // Display the string. fprintf(stderr,"Serveur cmd: %s\n",cmd); myErrExit("Echec dans la creation du process client"); }*/ Console::WriteLine(S"SERVEUR: Processus client cree avec succes, Attente de la connexion du fils au pipe"); // Attend que le processus fils se connecte pipeConnecte=ConnectNamedPipe(hPipe,NULL) ? TRUE :(GetLastError()==ERROR_PIPE_CONNECTED); if(pipeConnecte) { Console::WriteLine(S"SERVEUR: Connexion effectuee, création du thread de comm"); hThread = CreateThread( NULL, // no security attribute 0, // default stack size (LPTHREAD_START_ROUTINE) ThreadCommunication, // La fonction de départ du thread (LPVOID) hPipe, // thread parameter 0, // not suspended &dwThreadId); // returns thread ID if(hThread==NULL) myErrExit("Erreur dans la creation du thread communication serveur"); } Console::WriteLine(S"SERVEUR: Thread créé, entrée dans la boucle principale"); // Boucle principale do { //erreurPipe=(GetExitCodeThread(hPipe,&sortieThread)<=0)?TRUE:(sortieThread==STILL_ACTIVE); }while(1); FlushFileBuffers(hPipe); // vide le pipe pour le client CloseHandle(hPipe); //... et le ferme // Attend la fin du processus client Console::WriteLine(S"Processus client mort"); return 0; }
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 // Il s'agit du fichier projet principal pour le projet d'application VC++ // généré en utilisant un Assistant Application. #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <windows.h> #using <mscorlib.dll> using namespace System; /*###################################################################################*/ /* CONSTANTES #######################################################################*/ /*###################################################################################*/ #define BUFSIZE 128 #define PIPE_TIMEOUT 1000 /*###################################################################################*/ /* FONCTIONS ########################################################################*/ /*###################################################################################*/ /*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/ VOID myErrExit (LPTSTR lpszMessage) { LPVOID lpMsgBuf; int err; err=GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); fprintf(stderr,"Client Err:%d Msg:%s\n",err,lpMsgBuf); LocalFree(lpMsgBuf); fprintf(stderr, "Client: %s\n", lpszMessage); getchar(); ExitProcess(-1); } /*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/ VOID ThreadCommunication(LPVOID lpvParam) { CHAR msgDeIHM[BUFSIZE]; DWORD nbLus; BOOL lecReussie; int nbL=0; HANDLE hPipe; hPipe = (HANDLE) lpvParam; // Cast pour récupérer le handle du pipe // Synchronisation avec le client fprintf(stderr,"Entrée dans le thread comm avec handle n %d\n",hPipe); do { lecReussie=ReadFile( hPipe, msgDeIHM, BUFSIZE, &nbLus, NULL); if(lecReussie) { msgDeIHM[nbLus+1]='\0'; Console::WriteLine(msgDeIHM); } else { LPVOID lpMsgBuf; int err; fprintf(stderr,"CLIENT: Erreur reception\n"); err=GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); fprintf(stderr,"CLIENT Err:%d Msg:%s\n",err,lpMsgBuf); LocalFree(lpMsgBuf); } nbL++; }while((nbL<5000)&&(lecReussie)); if(!lecReussie) { fprintf(stderr,"Quitte le thread comm, erreur lect\n"); ExitThread(-1); } else { fprintf(stderr,"Quitte le thread comm Nb>lim\n"); ExitThread(0); } } /*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/ int _tmain(int argc, char *argv[]) { DWORD dwThreadId; // L'identifiant du thread HANDLE hPipe, // Handle du pipe hThread; // Handle du thread DWORD sortieThread; // BOOL pConnecte; // int nPipe; LPTSTR lpszPipename = "\\\\.\\pipe\\mynamedpipe"; // Nom du pipe int i; CHAR ch[50]; Console::Write(S"Nb Parametres:"); Console::WriteLine((int)argc); for(i=0;i<argc;i++) { sprintf(ch,"%d %s",i,argv[i]); Console::WriteLine(ch); } //sscanf(argv[argc-1],"%d",&nPipe); // Connection au pipe de communication Console::Write(S"CLIENT: Connexion au Pipe nomme n "); Console::WriteLine(lpszPipename); for(i=0;i<2000000;i++); //pConnecte=ConnectNamedPipe(hPipe,NULL); // On va ouvrir le pipe comme un fichier hPipe=CreateFile( lpszPipename, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hPipe==INVALID_HANDLE_VALUE) { myErrExit("Erreur dans la connexion au Pipe cote client"); } Console::Write(S"CLIENT: Connexion au Pipe nomme n°"); Console::Write((int)hPipe); Console::WriteLine(S" réussie, lancement du thread de communication"); hThread = CreateThread( NULL, // no security attribute 0, // default stack size (LPTHREAD_START_ROUTINE) ThreadCommunication, // La fonction de départ du thread (LPVOID) hPipe, // thread parameter 0, // not suspended &dwThreadId); // returns thread ID if(hThread==NULL) myErrExit("Erreur dans la creation du thread communication client"); getchar(); Console::WriteLine(S"CLIENT: Boucle principale"); // Boucle principale i=0; do { BOOL ecrReussie; DWORD nbEcrits; CHAR msgVersIHM[BUFSIZE]; float n=(float)rand()/100000; sprintf(msgVersIHM,"%03d_%1.6f",i,n); fprintf(stderr,"Envoi de %s (%d)vers %d\n",msgVersIHM,strlen(msgVersIHM)+1,hPipe); ecrReussie=WriteFile( hPipe, msgVersIHM, strlen(msgVersIHM)+1, &nbEcrits, NULL); if(!ecrReussie) { LPVOID lpMsgBuf; int err; err=GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); fprintf(stderr,"Client Err:%d Msg:%s\n",err,lpMsgBuf); LocalFree(lpMsgBuf); } fprintf(stderr,"Client Nb ecrits:%d long:%d\n",nbEcrits,strlen(msgVersIHM)+1); i++; GetExitCodeThread(hPipe,&sortieThread); }while((i<5000)); Console::WriteLine(S"Sortie client mort"); FlushFileBuffers(hPipe); // vide la pipe pour le client DisconnectNamedPipe(hPipe); // Déconnecte le pipe ... // Attend la fin du processus thread Console::WriteLine(S"Processus client mort"); return 0; }
Partager