Je me suis plongé à nouveau dans la doc de MSDN pour écrire ce client/serveur en overlapped, et je bute toujours. Je décris un peu le programme :
J'ai 2 threads:
1) le thread principal qui ouvre un pipe nommé en overlapped, puis qui boucle sur WaitForMultipleObjects(). Celle-ci attends 3 events manuels. Le premier est l'event qui permet de savoir si un client se connecte, le second permet de sortir de l'application, et le troisième devrait gérer les données arrivant dans le pipe (il est utilisé par ReadFile())
2) le deuxième thread n'est appelé que si le client se connecte. Il boucle sur ReadFile().
voici le code:
http://pastebin.com/5rka7dK7
Il y a principalement 4 fonctions (je ne compte pas la fonction qui affiche les erreurs):
a) svr_new: elle crée le pipe en overlapped et les events et appelle ConnectNamedPipe()
b) svr_del qui libère les ressources
c) _read_data_cb: le thread qui appelle ReadFile()
d) la fonction main, le thread principal, qui boucle sur WaitForMultipleObjects()
D'après la doc MSDN, vu que j'ouvre le pipe en overlapped, je dois passer une autre structure OVERLAPPED (dans le code, c'est svr->ol_read).
Maintenant, voici ce que je n'ai pas compris:
- est-ce que je dois appeler GetOverlappedResult() ?
- si oui, où ? Dès que le résultat de GetLastError() de ReadFile() renvoie ERROR_IO_PENDING (ligne 50 du paste) ? Quand WaitForMultipleObjects() retourne (ligne 303 du paste, je l'ai commenté) ? Ailleurs ?
- Je fais un ResetEvent() de l'event de Readfile() quand WaitForMultipleObjects() retourne (ligne 302 du paste). C'est au bon endroit ?
Avec le code que j'ai pasté, voici le résultat (le buffer de ReadFile() est de 5 octets) si le client envoie les 24 octets suivants :
Code : Sélectionner tout - Visualiser dans une fenêtre à part salut, c'est le client !Remarque: WaitForMultipleObjects() peut être appelé moins que ça. Ca a l'air aléatoire.
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 $ ./server.exe waiting for client... WaitForMultipleObjects : 0 client connected (1) WaitForMultipleObjects : 2 * ReadFile : 5 WaitForMultipleObjects : 2 * ReadFile : 5 WaitForMultipleObjects : 2 * ReadFile : 5 WaitForMultipleObjects : 2 * ReadFile : 5 WaitForMultipleObjects : 2 * ReadFile : 4
Donc getOverlappedResult() n'est pas appelé, ReadFile() réussit comme il faut (il lit 5*4 + 4 = 24 octets), mais je ne sais pas quand l'opération se termine.
Si je mets un printf() quand ReadFile() échoue avec ERROR_IO_PENDING, ce printf() est appelé indéfiniment.
De plus, le client envoie 2 messages. Celui ci-dessus, et un autre 2 secondes après. Le 2ème n'est jamais lu et ReadFile() "échoue" avec une erreur autre que ERROR_IO_PENDING ou ERROR_BROKEN_PIPE: ERROR_SUCCESS... (ReadFile() renvoie 0 et GetLastError() renvoie ERROR_SUCCESS)
Bref, je suis perdu. J'ai cherché des heures sur Internet, j'ai regardé les codes d'exemples de MSDN, du SDK, etc... Je ne pige toujours rien à ce que je dois faire dans mon cas particuliers.
Quelqu'un peut m'expliquer comment utiliser GetOverlappedResult() si on doit l'utiliser (et où l'utiliser), voire corriger mon code ?
Merci
Partager