2010-03-03 10 views
8

Je suis l'apprentissage sur les pipes nommés et joue avec les exemples de client de canal nommé et serveur dans le doc MSDN:Comment détecter une déconnexion d'un client à l'aide d'un client/serveur de canal nommé?

Named Pipe Server

Named Pipe Client

J'ai modifié le client, je peux taper des messages à la console et les envoyer au serveur où il affiche le message et renvoie une réponse. Essentiellement j'ai ajouté une boucle qui commence après l'appel de SetNamedPipeHandleState() et se termine avant l'appel de CloseHandle() (l'ouverture et la fermeture se produisent en dehors de la boucle, donc j'utilise le même handle de pipe dans la boucle). Ma question est la suivante: si je tue le client (en le fermant ou en le terminant via le Gestionnaire des tâches), le côté serveur peut-il détecter la déconnexion?

J'ai essayé d'utiliser GetNamedPipeHandleState() en espérant que l'échec de retour et un appel à GetLastError() retournerait ERROR_PIPE_NOT_CONNECTED, mais ce n'était pas le cas. En raison de la façon dont ce serveur est configuré, j'ai dû le faire dans la fonction CompletedReadRoutine et créer un échec "contrôlé". Ce que j'ai fait, avec un point d'arrêt sur le CompletedReadRoutine dans le serveur:

  1. démarré le serveur
  2. a commencé le client
  3. envoyé un message via le client (touche le point d'arrêt dans le serveur ici)
  4. tué le client
  5. étagé jusqu'à la GetNamedPipeHandleState

l'appel à retourne GetNamedPipeHandleState() succès complètement ainsi je n'ai jamais pu faire l'appel de GetLastError(). Quand il arrive à l'appel WriteFileEx, il échoue et un appel à GetLastError à ce point renvoie un ERROR_NO_DATA.

En regardant les fonctions de tuyau, je ne vois rien d'autre qui pourrait aider ici. Il me manque quelque chose ou une déconnexion client n'est pas détectable. La seule autre chose à laquelle je peux penser est de collecter les pid's des clients connectés (via GetNamedPipeClientProcessId) et de supprimer les threads watchdog pour vérifier s'ils sont toujours actifs. Cependant, juste en pensant à faire cela déclenche mon sens spider.

Existe-t-il un moyen de détecter les clients déconnectés lors de l'utilisation de canaux nommés?

Répondre

5

Ne renvoie pas ReadFile() et erreur et GetLastError() puis renvoie ERROR_BROKEN_PIPE?

+0

Seulement si je tue le client très soigneusement en utilisant des points d'arrêt dans le serveur afin que je puisse tuer le client à un piont spécifique dans la logique du serveur. Par exemple, si je démarre le client et le tue juste après la connexion initiale mais avant la première fois que le serveur appelle ReadFileEx, alors oui j'obtiens ERROR_BROKEN_PIPE. Le problème est le serveur attend sur l'appel à WaitForSingleObjectEx. Si le côté client tombe en panne, il n'écrit pas ou ne lit pas à partir de ce dernier préalablement connecté à l'instance de canal. –

+3

Je ne pense pas vraiment que ces exemples sont un bon exemple de la façon de faire les choses ... Personnellement, j'ai toujours une lecture chevauchée en attente sur le tuyau, de cette façon, vous devriez toujours recevoir une notification lorsque le client s'en va. .. –

+0

Je vous entends et je suis d'accord que les exemples que j'ai ne sont pas ce que je devrais regarder pour la façon dont je voudrais que la communication fonctionne. Merci pour votre contribution. –

1

ReadFile() + GetLastError() faites bien le travail. Voici comment ils peuvent être utilisés avec E/S ports d'achèvement (ma mise en œuvre est en python + ctypes, mais l'idée doit être clair):

def connect(): 
    GetQueuedCompletionStatus() 
    receive() 

def receive(): 
    while True: 
     ret_code = ReadFile() 
     if ret_code == 0 and GetLastError() == ERROR_BROKEN_PIPE: 
      # client disconnected 
     GetQueuedCompletionStatus() 

Nous attendons un paquet d'achèvement, et quand un client se connecte , nous passons à la boucle principale. Dans la boucle principale, nous lisons le canal et vérifions si le client s'est déconnecté en regardant ReadFile() code retour et GetLastError(). Ensuite, nous attendrons un paquet d'achèvement.

Un client peut se déconnecter à n'importe quel stade. Le paquet d'achèvement sera mis en file d'attente et nous obtiendrons ERROR_BROKEN_PIPE.

+0

Quel langage de programmation est-ce? Il ressemble un peu à Python, mais AFAIK 'winapi' est C, C++, C# et Visual Basic seulement. – wizzwizz4

+0

Oui, c'est Python, mais vous pouvez appeler les fonctions winapi en utilisant la bibliothèque ctypes. Un mécanisme qui permet cela est appelé FFI: https://en.wikipedia.org/wiki/Foreign_function_interface – wombatonfire