6
votes

TCplistener: Détecter une déconnexion client par opposition à un client n'envoie aucune donnée pendant un certain temps.

Je cherchais à détecter une "déconnexion du client" lors de l'utilisation d'un TCplistener.

Toutes les réponses semblent être similaires à celle-ci: TCplistener: Comment puis-je détecter un client déconnectez-vous?

Fondamentalement, lisez à partir du flux et s'il est lu () renvoie 0 Le client avait déconnecté.

Mais cela suppose qu'un client déconnecte après chaque flux de données envoyé. Nous opérons dans des environnements où le TCP Connect / déconnectez les frais généraux est à la fois lent et coûteux.

Nous établissons une connexion, puis nous envoyons un certain nombre de demandes.

pseudocode: xxx

Chaque appel entre Connect et Deconnect () envoie un flux de données sur le serveur. Le serveur sait comment analyser et traiter les flux.

Si vous laissez le TCplistener lu dans une boucle sans jamais le déconnecter de la lecture et gère tous les messages, mais après la déconnexion du client, le serveur n'a aucun moyen de savoir et il ne relâchera jamais le client et acceptera de nouvelles. xxx

si je laisse le TCplistener déposer le client lors de la lecture == 0 Il n'accepte que Le premier flux de données uniquement pour déposer le client immédiatement après.

Bien sûr, cela signifie que de nouveaux clients peuvent se connecter.

Il n'y a pas de retard artificiel entre les appels, Mais en termes de temps d'ordinateur, le temps entre deux appels est «énorme» bien sûr, donc il y aura toujours un temps où lire == 0 même si cela ne veut pas dire Le client a ou doit être déconnecté. xxx

donc je me demande ... Y a-t-il un meilleur moyen de détecter si le client a déconnecté?


0 commentaires

3 Réponses :


2
votes

Vous pouvez obtenir la prise sous-jacente à l'aide de la propriété NetworkStream.sockt et utilisez-la est recevoir la méthode de lecture.

Contrairement à NetworkStream.read , la surcharge liée de socket.receive bloquera jusqu'à ce que le nombre spécifié d'octets ait été lu et ne reviendra que zéro si l'hôte distant arrête la connexion TCP.


Mise à jour: Le commentaire de JRH est correct que NetworkStream.socket est une propriété protégée et n'est pas accessible dans ce contexte. Afin d'obtenir le client , vous pouvez utiliser le TCPLISTENER.ACceptsockt Méthode qui renvoie l'objet de la prise correspondant à la connexion nouvellement établie.


4 commentaires

NetworkStream.sockt n'est pas exposé octet L'instance de Networkstream renvoyée par tcplistener.getstream (). Mais je cherche maintenant à l'aide de la classe de socket directement


OK, en utilisant les sockets directement et que l'utilisation de la méthode de réception fonctionne comme un charme. Une capture d'essai est nécessaire lors de l'acceptation du client et d'essayer de recevoir. Thnx!


Pourquoi ne vous donne pas accès à Networkstream.sockt quand il donne un accès à quasi sans restriction à tcpclient S socket 'S à l'aide du client ? Est-ce juste un .NET DESIGN QUIRIK, ou existe-t-il un scénario où il est logique de ne pas pouvoir obtenir un socket Socket? De plus, vous voudrez peut-être réviser cette réponse car NetworkStream.socket est protégé et non accessible.


@jrh Vous avez raison sur la propriété protégée, j'ai mis à jour la réponse. Très probablement, NetworkStream ne donne pas accès direct à la prise, car elle offre la capacité de limiter les lectures et les écritures. Voir le constructeur Surcharges avec paramètre FileAccess.



3
votes

La réponse d'Eren a résolu le problème pour moi. Au cas où quelqu'un d'autre est confronté au même problème Voici un code "échantillon" à l'aide de la méthode Socket.Receive: xxx

Vous appelez acceptClientandProcess () dans une boucle quelque part.

La ligne suivante: < Pré> xxx

bloquera jusqu'à

  • Les données sont reçues (lisez> 0) auquel cas vous pouvez le gérer
  • La connexion a été fermée correctement (LIVE = 0)
  • La connexion a été fermée brusquement (une exception est lancée)

    L'une des deux dernières situations indiquez que le client n'est plus connecté.

    L'essais attrape autour de la méthode Socket.Accept () est également requise Comme il peut échouer si la connexion du client est fermée brusquement pendant la phase de connexion.

    Notez qui spécifie un délai d'attente de 20 secondes pour l'opération de lecture.


0 commentaires

1
votes

La documentation de Networkstream .Read ne reflète pas cela, mais dans mon expérience, des blocs "Networkstream.Read" si le port est toujours ouvert et qu'aucune donnée n'est disponible, mais renvoie 0 si le port a été fermé.

J'ai couru dans Ce problème de l'autre côté , dans ce Networkstream .Read ne renvoie pas immédiatement 0 si aucune donnée n'est actuellement disponible. Vous devez utiliser NetworkStream.DataAnvailable pour savoir si NetworkStream.read peut lire des données en ce moment.


0 commentaires