2010-06-22 4 views
4

J'utilise un ElSSLSocket de C#. C'est un socket SecureBlackBox. SecureBlackBox est une bibliothèque tierce pour gérer les sockets sécurisés.Comment puis-je savoir quand un socket s'est déconnecté

Je peux voir que l'objet ElSSLSocket a une propriété appelée 'Socket' de sorte que le socket sous-jacent est un socket .NET normal.

Ma question, y a-t-il une sorte d'événement auquel je peux m'abonner pour que je puisse voir quand le socket se déconnecte mal? J'ai une connexion au serveur client qui va souvent se déconnecter. Il est difficile de voir si c'est le client ou le serveur, et difficile de voir la cause réelle.

Je suis assez sûr qu'il y a quelques problèmes de logique dans l'application, c'est-à-dire que ceci n'est pas causé par des pannes de réseau ou quelque chose comme ça.

Je dois également vous faire savoir que les déconnexions que je reçois sont cette erreur,

SocketException - Une connexion existante a été fermée de force par l'hôte distant

ErrorCode - 10054

S'il y avait un manière que je pourrais réellement trouver la cause de cela?

+0

S'IL VOUS PLAÎT pouvez-vous les gens utiles regarder ce nouveau poste, je l'ai fait, http://stackoverflow.com/questions/3098652/why-does-my-client-server-socket-connection-keep-disconnecting J'ai décidé d'utiliser wireshark pour voir ce qui se passe. – peter

Répondre

4

La détection des connexions demi-ouvertes est l'un des classic socket programming scenarios. La propriété Socket.Connected est complètement inutile et Socket.Poll ne fonctionne pas pour toutes les situations. Il est préférable d'envoyer un message "heartbeat" toutes les quelques secondes.

10054 est l'un des common errors. Cela signifie que la connexion a été perdue (pas correctement fermée). Il peut être provoqué par l'arrêt de l'ordinateur distant, la fermeture du processus distant ou même le redémarrage d'un routeur intermédiaire.

+0

C'est la seule façon de le faire. J'ai passé plusieurs mois à travailler avec des douilles et c'est la conclusion. Alternativement, vous pouvez simplement utiliser WCF qui fera disparaître tous vos problèmes. – NibblyPig

+0

@SLC - Je n'appellerais pas exactement WCF une panacée. Parfois, vous voulez la simplicité Sockets over charpente de l'armature. – ChaosPandion

+0

Je devine où je veux arriver à savoir qui déconnecte d'abord, le client ou le serveur. La connexion de socket peut en fait être hors de portée, c'est-à-dire qu'une erreur de programme se produit qui n'est pas signalée, mais qui provoque une exception dans la pile. Genre de difficile à expliquer. – peter

1

J'ai trouvé que cela fonctionne très bien:

Réception

_socket.Poll(100, SelectMode.SelectRead) && _socket.Available == 0 

Envoi

!_socket.Poll(100, SelectMode.SelectWrite) 
+0

OK. Merci. J'ai fait un test, je fais un 'write' sur une socket à partir du client, donc j'ai déconnecté la fin du serveur. J'ai donc raison d'appeler _socket.Poll (100, SelectMode.SelectWrite)? Et devrais-je m'attendre à un résultat faux? Le résultat était vrai. La chose que j'ai remarquée est que la propriété 'Connected' est devenue fausse avant l'appel suivant 'Send' à la fin du client. Je pourrais essayer et utiliser cela. Qu'est-ce que tu en penses? – peter

+0

@peter - Ne pas oublier le '!'. – ChaosPandion

+0

Y at-il une différence entre le type de sockets que vous utilisez par rapport à moi? J'utilise des douilles de blocage. Aussi, quand vous appelez 'Sondage', que fait-il réellement? Vérification de la prise distante est-elle connectée? Ou simplement vérifier que la prise locale fonctionne comme prévu? Peut-être que c'est lent à réagir à la déconnexion. – peter

2

Bien que cela est écrit dans C, vous devriez être en mesure de faire la même chose dans C#:

int dummy; 
// since you're just testing if the socket is still open for reading you don't 
// want it to block, or remove data from the sockets recv buffer 
int ret = recv(sockfd, &dummy, sizeof dummy, MSG_DONTWAIT | MSG_PEEK); 

if ((ret == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) 
     || ret > 0) { 

    // socket is still open for reading 

else if (ret == 0) { 

    // socket went through orderly shutdown and is closed for reading 

} else { 

    // there is some error and the socket is likely closed 
    // check errno 

} 

Supposons que vous pensez qu'il est à moitié fermé et vous avez encore des données que vous voulez écrire.

int myData = 0xDEADBEEF; 
int ret = send(sockfd, myData, sizeof myData, MSG_NOSIGNAL); 

De cette façon, si la prise est complètement fermé votre envoi ne sera pas tuer votre programme avec un SIGPIPE. Au lieu de cela, l'appel renverra -1 et définira errno à EPIPE.

Questions connexes