Je développe un serveur en C # qui peut accepter un seul client et je dois savoir quand ce client est déconnecté pour pouvoir accepter d'autres demandes de connexion. P>
J'utilise une première prise qui écoute en permanence la demande de connexion avec Pour détecter si le client a été déconnecté, j'ai installé une minuterie qui envoie tous les 500 ms un message vide (" J'ai essayé d'envoyer un tampon vide ( Une autre solution peut être de gérer le cas où J'ai déjà vu plusieurs threads et questions sur ce problème, mais je n'ai jamais vu de bonne solution. P>
Donc, ma question est la suivante: quelle est la meilleure façon de détecter une déconnexion dans .NET? P> socket.beginaccept code> et accepter ou rejeter les clients. Lorsqu'un client est accepté, la nouvelle prise renvoyée par
socket.endaccept code> est utilisée pour la communication entre client et serveur. Ensuite, le serveur attend les commandes du client avec
socket.begin / endreceive code> et envoie des réponses. Le serveur utilise un protocole de type Telnet, ce qui signifie que chaque commande et chaque ligne de réponse doivent se terminer par
\ r \ n code>. P>
\ r \ n code>") au client. Si le client est déconnecté, une exception est lancée par la prise. Cette exception est capturée par le serveur qui ferme la session en cours et accepte la nouvelle connexion. Cette solution est robuste mais implique un trafic inutile sur le réseau et doit être traité correctement par le client qui doit filtrer des messages factices avant d'obtenir une réponse réelle. p>
socket.send (nouvel octet [1], 0, 0) code>), mais il semble que cela ne fonctionne pas dans la direction Server-> client. P>
socket.endreceive code> retourne 0 octet. Cela fonctionne bien pour le cas d'une déconnexion qui se produit pendant le temps "inactif". Mais si le client se déconnecte pendant un transfert de message, le serveur ne le voit pas toujours et attend indéfiniment. P>
4 Réponses :
La seule autre option est si elle est TCP, c'est que TCP soit envoyé un conservateur de tous deux, ce qui sonne toujours telle que ce que vous faites maintenant mais géré à la couche TCP, donc votre protocole n'est donc pas un protocole. t besoin de savoir. p>
Il n'y a aucun moyen de contourner cependant, car sans envoyer quelque chose à l'autre client et avoir une réponse, vous n'avez aucun moyen de savoir s'il est toujours connecté ou non. P>
Garder en vie peut également être nécessaire de toute façon lors de la communication à travers une inspection de paquets étatique telle que Standard NAPT afin d'éviter que le serveur distant dépose la session en raison de l'activité intégraine. P>
OK, j'ai ajouté du code qui permet à Keepalive pour ma prise. Mais que suis-je supposé attendre maintenant? Rien ne se passe lorsque le client enfreint la connexion ... Je m'attendais à recevoir une exception quelque part ... Devrais-je lire ou écrire quelque chose périodiquement?
Je suppose que vous utilisiez début / endreceive? Si tel est le cas, le débutant doit exécuter le rappel et lorsque vous appelez EndReceive pour obtenir le résultat, une exception doit être soulevée, qui ou une fin de flux 0 octet.
Ok, je reçois une exception maintenant ... merci
Vous pouvez utiliser la méthode ci-dessous pour rechercher si un client est toujours connecté. Ceci ceci Réponse est destiné à la prise de test, ce que j'ai eu mon extrait de code. P> p>
Cette méthode fonctionne bien si le client a explicitement fermé la connexion, mais pas si la connexion a été brisée (câble débranché par exemple).
Ce qui est là où se situe en vie, le protocole OS et TCP traitera des messages périodiques au client pour voir s'il est vivant et interrogera le socket vérifiera l'état local. Si un service alive échoue, la prise doit signaler que son n'est plus connecté.
Bien que lorsque vous utilisez Async Begn / Endreceive, le sondage ne doit pas être requis car vous devriez recevoir un appel avec l'erreur lorsque la prise échoue à rester en vie.
Cette méthode souffre d'une condition de race qui conduit à de faux positifs, comme indiqué Ici .
Avez-vous un contrôle sur le client? Si tel est le cas, vous ne pouvez pas que le client envoie un paquet spécial au serveur indiquant qu'il se déconnecte, puis débranchez la prise? P>
essayez-vous de détecter le cas que le client a réellement déconnecté (à l'aide de socket.ShuTown () ou de socket.close ()) ou si le client est inactif pour une quantité énorme de temps et doit donc être éjecté? p>
Dans les deux cas, demandez au client d'envoyer un message périodique (comme vous l'avez fait) sur le serveur. Le serveur peut garder une trace du dernier battement de coeur et si le client manque plus de 3 cardiaques, vous pouvez déconnecter le client. Oui, cela implique des données supplémentaires, mais ce n'est pas trop mauvais dans le grand schéma des choses. Si vous l'ajustez de manière à ce qu'il envoie le battement de coeur à une bonne période suffisante, de sorte que vous obteniez l'avantage de savoir si le client est en vie et que vous n'êtes pas trop long entre les battements cardiaques, vous pourriez avoir un très bon système. P >
La seule chose que ce genre de sujet qui m'aime vraiment est lorsque vous lisez un flux de réseau et cela revient un zéro. Cela indique généralement une déconnexion de réseau mais, pour une raison d'étrange, elle n'augmente pas une exception. Donc, votre bloc de capture traitant très écrit ne fonctionne pas. Ma solution a été de créer une méthode de lecture de wrapper où vous vérifiez un retour à zéro et augmentez votre propre exception. Il me semble toujours qu'un retour zéro devrait soulever une exception.