OVH Cloud OVH Cloud

questions sur un client/serveur utilisant un tube nomm

13 réponses
Avatar
torri
j'ai écrit un client/serveur utilisant les tubes nommés. Le serveur
utilise l'overlapped I/O (je ne sais pas comment trraduire ceci). Je me
suis inspiré beaucoup de [1] et [2] car je ne connais pas énormément de
choses à propos des tubes nommés et des clients/serveurs. Voici mes codes:

Le serveur: http://www.maths.univ-evry.fr/pages_perso/vtorri/files/
server2.c

Le client: http://www.maths.univ-evry.fr/pages_perso/vtorri/files/
client2.c

Donc, dans le code du serveur (uniquement pour l'instant), quand je veux
lire des données, je lance un thread avec une boucle sur PeekNamedPipe(),
et dès qu'il y a des données, je quitte le thread. Puis quand
WaitForMultipleObjects() me rend la main lorque que le thread se termine,
je fais une boucle sur ReadFile() et je récupère les données.

Je voudrais savoir s'il existe un moyen de savoir si des données sont
disponibles avec WaitForMultipleObjects(), celle-ci retournant quand une
donnée doit être lue, plutôt que créer un thread avec PeekNamedPipe()
(j'aimerais éviter les threads le plus possible. En plus il me prend 100%
du CPU).

L'autre question : pour quitter le client, je fais juste un CloseHandle
sur l'handle renvoyé par CreateFile(). Mais je n'arrive pas, côté
serveur, à savoir si le client s'est déconnecté. Comment dois-je faire
pour que le serveur soit notifié de la déconnection du client ? (pareil
dans l'auter sens : si le serveur se déconnecte, comment le client peut
le savoir)

Merci

3 réponses

1 2
Avatar
Thierry
torri écrivait
news:imrsto$h1a$:

On Mon, 28 Mar 2011 11:54:08 +0200, Antoine wrote:

Oui, c'est le meme principe dans tous les exemples de MS On choisit
un buffer de taille fixe ou dynamique (malloc-realloc), qui se
remplit en bouclant sur une api de lecture (ReadFile,
InternetReadFile, ..)



dans ce cas, j'ai un problème. J'ai ouvert le pipe en overlapped,
donc ReadFile() et WriteFile() peuvent retourner tout de suite si
l'opération prend trop de temps (le code d'erreur retourné par ces 2
fonctions est ERROR_IO_PENDING dans ce cas). ReadFile() renvoie cette
erreur, mais je n'arrive pas à m'en sortir avec les events

Voici le code du serveur avec la méthode du SDK (le client est dans
le 1er post, son code n'a pas changé):

http://dpaste.org/crQq/

En gros:

dans mon thread principal, je fais une boucle infinie qui appelle
WaitForMultipleobjects(). Il y a 2 ou 3 objects qui sont gérés :
l'event du pipe, un event général pour quitter la boucle et en 3ème
un event pour ReadFile().



A moins que je n'ai loupé quelque chose, tu n'as pas besoin de faire le
ReadFile en asynchrone puisque du fais de l'overlapped sur la lecture du
pipe: les données sont là quand tu reçois l'event sur le pipe (param
PIPE_WAIT a la création du pipe). Et ça t'evite de gerer 2 fois les même
code d'erreur.

Init
boucle
WaitForMultpleObjects
ReadFile

De



Sur la forme:
- le code n'est vraiment pas lisible. Evite les var globales. Tu eviteras
pas mal d'erreurs
- vire tous les goto: c'est incompatible avec de la prog systeme.
Initialise TOUTES tes variables lors de la déclaration et si tu dois faire
du mênage en fin de fonction tu testes si la variable a été initialisée
pour la nettoyer si besoin.
- utilse un event avec auto reset: là si d'autres données sont envoyées
dans le pipe entre le WFMO et le Reset tu vas les louper.
- nbr_objects est a 2: alors que tu as 3 objets.
- pas besoin de alloc / realloc le buffer de lecture: tu spécifie une
taille max dans la creation de ton pipe




une fois que le client se connecte, je lance un thread qui fait une
boucle infinie pour lire les données arrivant du client. ReadFile()
est appelé et je gère l'erreur.

Dès qu'une donnée arrive du client, ERROR_IO_PENDING est retourné
et je n'arrive pas à faire en sorte que WaitForMultipleObjects()
retourne quand j'appelle SetEvent().

J'ai essayé beaucoup de choses (avoir l'event dès le début, le
rajouter en cours de route, etc...). Rien à faire, je n'arrive pas à
faire fonctionner correctement ReadFile().

Donc si quelqu'un a une idée...

merci






--
Vainqueur du 1er WSOFRJCP
Avatar
torri
On Tue, 29 Mar 2011 10:43:54 +0000, Thierry wrote:


A moins que je n'ai loupé quelque chose, tu n'as pas besoin de faire le
ReadFile en asynchrone puisque du fais de l'overlapped sur la lecture du
pipe: les données sont là quand tu reçois l'event sur le pipe (param
PIPE_WAIT a la création du pipe). Et ça t'evite de gerer 2 fois les même
code d'erreur.



donc je peux même faire un PeekNamedPipe() pour tester l'arrivée des
données ?


Init
boucle
WaitForMultpleObjects
ReadFile

De



Sur la forme:
- le code n'est vraiment pas lisible. Evite les var globales. Tu
eviteras pas mal d'erreurs



c'est une prog de test. J'essaie de faire en sorte que ça marche. Après,
je dois intégrer ça dans un framework (je fais le port Windows d'une lib
qui fonctionne sous Unix)

- vire tous les goto: c'est incompatible avec de la prog systeme.



pas d'accord, ca peut optimizer la taille du code. Je ne fais des goto
que dans un cas tres particulier (gestion des erreurs lors de
l'initialisation (fonction *_new()). Ici j'ai utilise des goto un peu
plus que necessaire, néanmoins, mais c'est un prog de test.

Initialise TOUTES tes variables lors de la déclaration et si tu dois
faire du mênage en fin de fonction tu testes si la variable a été
initialisée pour la nettoyer si besoin.



je fais du C ANSI, donc
1) déclaration des variables en début de bloc
2) il y a des cas où je (ne peux pas/il est inutile d') initialiser ces
variables.

en C99/C++, ces restrictions n'ont plus lieu d'être.

C'est juste une différence de style de code. Je suis un coder linux et je
trouve les codes des codeurs Windows difficile à lire. C'est juste une
habitude, je suppose.

- utilse un event avec auto reset: là si d'autres données sont envoyées
dans le pipe entre le WFMO et le Reset tu vas les louper. - nbr_objects
est a 2: alors que tu as 3 objets.



le coup de nbr_object est pourri, c'est une tentative de gérer l'event de
l'overlapped du ReadFile(), qui s'est soldé par un échec pour toutes mes
tentatives. Si PeekNamedPipe() est utilisable dans mon cas, je n'ai plus
besoin de cet event.

- pas besoin de alloc / realloc le
buffer de lecture: tu spécifie une taille max dans la creation de ton
pipe



Ca deviendra inutile avec PeekNamedPipe(), je pense.

Merci pour la lecture du code :-)
Avatar
torri
Je viens de regarder plus précisément la doc.

Je crée, côté serveur, le pipe en overlapped.

Doc de ConnectNamedPipe():

"If hNamedPipe was opened with FILE_FLAG_OVERLAPPED, the lpOverlapped
parameter must not be NULL."

Doc de ReadFile():

"If hFile is opened with FILE_FLAG_OVERLAPPED, the lpOverlapped parameter
must point to a valid and unique OVERLAPPED structure, otherwise the
function can incorrectly report that the read operation is complete."

Donc que ce soit en PIPE_WAIT ou PIPE_NOWAIT, de toute façon je dois
passer une structure OVERLAPPED à ReadFile() et ConnectNamedPipe().

Ou alors, il y a une incompatibilité entre passer FILE_FLAG_OVERLAPPED et
PIPE_WAIT, ce qui semblerait bizarre car l'exemple du SDK utilise
justement ces 2 valeurs.
1 2