Comment détecter une Prise de Déconnexion en C#
Je suis en train de travailler sur un client/serveur de relation, qui est destinée à envoyer des données en arrière et en avant pour un montant indéterminé de temps.
Le problème, je vais tenter de surmonter est sur le côté client, étant que je n'arrive pas à trouver un moyen pour détecter une déconnexion.
J'ai pris un couple de passes à d'autres peuples de solutions, allant de la juste attraper IO Exceptions, aux bureaux de la prise de courant à trois SelectModes. J'ai aussi essayé en utilisant une combinaison d'un sondage, avec un contrôle sur le "Disponible" domaine de la prise.
//Something like this
Boolean IsConnected()
{
try
{
bool part1 = this.Connection.Client.Poll(1000, SelectMode.SelectRead);
bool part2 = (this.Connection.Client.Available == 0);
if (part1 & part2)
{
//Never Occurs
//connection is closed
return false;
}
return true;
}
catch( IOException e )
{
//Never Occurs Either
}
}
Sur le côté serveur, une tentative d'écriture d'un "vide" de caractère ( \0 ) pour le client forces ar Exception et que le serveur peut détecter que le client s'est déconnecté ( assez facile de concert ).
Sur le côté client, la même opération donne aucune exception.
//Something like this
Boolean IsConnected( )
{
try
{
this.WriteHandle.WriteLine("//Something like this
Boolean IsConnected( )
{
try
{
this.WriteHandle.WriteLine("\0");
this.WriteHandle.Flush();
return true;
}
catch( IOException e )
{
//Never occurs
this.OnClosed("Yo socket sux");
return false;
}
}
");
this.WriteHandle.Flush();
return true;
}
catch( IOException e )
{
//Never occurs
this.OnClosed("Yo socket sux");
return false;
}
}
Un problème que je crois que je vais avoir dans la détection d'une déconnexion par un sondage, c'est que je peux assez facilement à la rencontre d'une faux sur un SelectRead, si mon serveur n'a pas encore écrit quelque chose de nouveau pour le client depuis la dernière case... ne sais Pas quoi faire, j'ai chassé en bas de chaque option pour faire de la détection que je peux trouver, et rien n'a été de 100% pour moi, et, finalement, mon but ici est de détecter un serveur (ou connexion) échec, d'en informer le client, attendre pour vous reconnecter, etc. Donc, je suis sûr que vous pouvez imaginer que c'est une partie intégrante de la pièce.
Apprécie quelqu'un de suggestions.
Merci à l'avance.
EDIT: Personne visualisation de cette question devrait prendre note de la réponse ci-dessous, et mon dernier commentaire. J'ai élaboré sur comment j'ai surmonté ce problème, mais n'ont pas encore fait un Q&Un style post.
J'ai essayé déjà ( au cas où vous n'avez pas vraiment lu mon post... ) et il est frappé ou manquer. Une opération de lecture d'expirer après une seconde provoque une IO, ce qui pourrait forcer une déconnexion... Mais si je n'en ai pas reçu de données...?
J'ai lu votre post. Il n'est pas "hit and miss", il est soumis à des données asynchrone de mise en mémoire tampon à la fois localement et à distance. Vous n'obtiendrez pas une exception lors de la première écriture d'un échec de la connexion, qu'elle n'a pas encore été détectés: vous l'obtiendrez à la suite d'écrire, après que le protocole TCP a dépassé le nombre de tentatives.
Désolé de le dire, je suis en total désaccord. Je peux Fraps une session de Débogage si vous le voulez bien...
Socket.Recevoir et EndReceive() renvoie zéro lorsque la distance a fait un arrêt sur le côté. Ceci est documenté dans la description de l'API: Si vous utilisez une connexion de Socket, la méthode de réception sera lu comme la quantité de données est disponible jusqu'à la taille de la mémoire tampon. Si l'hôte distant s'arrête la connexion de Socket de la méthode d'Arrêt, et l'ensemble des données disponibles a été reçu, la méthode de réception seront exécutés immédiatement et retour à zéro octets.
OriginalL'auteur DigitalJedi805 | 2012-08-06
Vous devez vous connecter pour publier un commentaire.
Une option est d'utiliser le protocole TCP keep alive paquets. Vous allumez avec un appel à
Socket.IOControl()
. Seulement peu ennuyeux, c'est qu'il prend un tableau d'octets en entrée, donc vous devez convertir vos données en un tableau d'octets à transmettre. Voici un exemple d'utilisation d'un 10000ms garder en vie avec un 1000ms réessayer:Garder en vie les paquets sont envoyés que si vous n'êtes pas envoyer d'autres données, de sorte que chaque fois que vous envoyez des données, la 10000ms minuterie est remise à zéro.
Hey Joel, donc je crois que j'ai trouvé l'idée ici, mais s'il vous plaît corrigez-moi si je suis mal; Le IOControl méthode met un temps de livraison d'un "KeepAlive' paquet sur un socket. J'ai ajouté ( presque mot pour mot), le code ci-dessus à mes deux SocketServer.Client, et SocketClient constructeurs. J'ai réduit la minuterie jusqu'à une deuxième ( puisque c'est le délai d'attente sur mon "lire" sur les deux côtés? ) mais mon StreamReader.ReadLine ( Juste de me rendre compte que la messagerie instantanée en tapant ce que ce ne devrait pas être ma stratégie ) attrape jamais toutes les données... je dois dire que je ne suis pas sûr exactement pourquoi nous mettons ce que nous mettons dans le tableau; puis-je en ligne-mettre fin?
En fait juste essayé de courir la même chose avec un StreamReader.Lire l'appel, et encore jamais eu quoi que ce soit dans les deux sens. Peut-être que je ne comprends pas tout le concept.
Je suis raisonnablement certain de la garder vivante est mangé avant de voir quoi que ce soit. Pour la tester, exécutez vos applications sur des machines différentes et lancez wireshark pour examiner les données. Vous devriez voir la garder vivante sortir et d'une réponse de revenir (si tout est lié), mais votre read() appel de ne pas voir quoi que ce soit.
Qui est correct. Lors de l'utilisation de cela, il n'est pas nécessaire de faire appel à SetSocketOption().
OriginalL'auteur Joel Rondeau