questions sur un client/serveur utilisant un tube nomm
13 réponses
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)
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, ..)
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
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, ..)
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
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, ..)
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
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 :-)
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.
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 :-)
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.
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.
"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.