Comment vérifier si un socket est connecté/déconnecté en C#?
Comment pouvez-vous vérifier si une prise réseau (Système d'.Net.Les Sockets.Socket) est toujours connecté si l'autre hôte ne pas vous envoyer un paquet lorsqu'il se déconnecte (par exemple, parce qu'il était débranché ungracefully)?
Vous devez vous connecter pour publier un commentaire.
Comme Paul Turner répondu
Socket.Connected
ne peut pas être utilisé dans cette situation. Vous avez besoin d'un sondage de connexion à chaque fois pour voir si la connexion est toujours active. C'est le code que j'ai utilisé:Il fonctionne comme ceci:
s.Sondage
retourne true sis.Disponible
renvoie le nombre d'octets disponibles pour la lectureAvailable
de la propriété. Selon lePoll
de la méthode page MSDN, elle renvoie true également si les données sont disponibles pour la lecture.return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0)
Poll
méthode de la page MSDN:This method cannot detect certain kinds of connection problems, such as a broken network cable, or that the remote host was shut down ungracefully. You must attempt to send or receive data to detect these kinds of errors.
Comme zendar écrit, il est bien d'utiliser la
Socket.Poll
etSocket.Available
, mais vous devez prendre en considération le fait que le support n'aurait pas été initialisé en premier lieu. C'est la dernière (je crois) le morceau de l'information et il est fourni par leSocket.Connected
de la propriété. La version révisée de la méthode ressemble à quelque chose comme ceci:La
Socket.Connecté
propriété vous permet de savoir si un socket pense il est connecté. Il reflète en fait l'état de la dernière envoyer/recevoir de l'opération effectuée sur le socket.Si le socket a été fermée par vos propres actions (débarrasser de la douille, l'appel de méthodes à déconnecter),
Socket.Connected
sera de retourfalse
. Si le support a été déconnecté par d'autres moyens, la propriété sera de retourtrue
jusqu'à la prochaine tentative d'envoyer ou de recevoir de l'information, à quel point unSocketException
ouObjectDisposedException
sera levée.Vous pouvez vérifier la propriété après l'exception a eu lieu, mais il n'est pas fiable avant.
J'ai fait une extension de la méthode basée sur cette article MSDN.
C'est comment vous pouvez déterminer si un socket est toujours connecté.
Accepté la réponse ne semble pas fonctionner si vous débranchez le câble réseau. Ou les pannes de serveur. Ou de votre routeur se bloque. Ou si vous avez oublié de payer votre facture internet. Ensemble TCP keep-alive options pour une meilleure fiabilité.
La valeur de temps définit le délai d'attente étant donné que les données a été dernier envoi. Puis il tente d'envoyer et de recevoir un paquet keep-alive. Si elle échoue, elle réessaie 10 fois (nombre codé en dur depuis Vista autant que je sache) dans l'intervalle de temps spécifié avant de décider de la connexion est mort.
Donc les valeurs ci-dessus entraînerait 2+10*1 = 12 seconde de détection. Après que toute lecture /wrtie /sondage opérations d'échec sur le socket.
La meilleure façon est de simplement avoir votre client d'envoyer un PING toutes les X secondes, et pour le serveur de supposer qu'il est déconnecté après n'avoir pas reçu de l'un pendant un certain temps.
J'ai rencontré le même problème que vous quand à l'aide de sockets, et c'était la seule façon que je pouvais le faire. Le socket.connecté à la propriété n'a jamais été correct.
À la fin, cependant, je suis passé à l'aide de la WCF, car il est beaucoup plus fiable que les sockets.
En suivant les conseils de NibblyPig et zendar, je suis venu avec le code ci-dessous, qui fonctionne sur tous les test que j'ai fait. J'ai fini par en avoir besoin à la fois le ping, et le sondage. Le ping me permettra de savoir si le câble est débranché, ou de la couche physique, autrement perturbé (routeur hors tension, etc). Mais parfois, après reconnectez-je obtenir une première, le ping est ok, mais l'état tcp n'est pas.
Comme Alexander Enregistreur souligné dans zendars réponse, vous devez envoyer quelque chose pour être complètement sûr.
Dans le cas où votre partenaire de connexion, ne lisez sur cette prise, vous pouvez utiliser le code suivant.
Mais même alors, il peut prendre quelques secondes jusqu'à ce qu'un bris de câble réseau ou quelque chose de similaire est détecté.
Suffit d'utiliser la directive KeepAlive comme @toster-cx dit, puis utilisez la Prise état Connecté pour vérifier si la Prise est toujours connecté. Définissez votre délai de réception (dans le même délai d'attente de la keepalive. Si vous avez d'autres questions, je suis toujours heureux d'aider!
Utilisation
Socket.Connecté
Propriété.