102 votes

Détection de la déconnexion d'un client TCP

Disons que je fais tourner un serveur simple et que j'ai accept() ed une connexion d'un client.

Quelle est la meilleure façon de savoir si le client s'est déconnecté ? Normalement, un client est censé envoyer une commande de fermeture, mais que se passe-t-il s'il se déconnecte manuellement ou perd complètement la connexion réseau ? Comment le serveur peut-il détecter ou gérer cette situation ?

0 votes

Regardez ici (pour les pires scénarios) : tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html (Vérification des pairs morts)

5 votes

Parce qu'il y a tellement de réponses fausses et trompeuses, voici la bonne réponse : Suivez les spécifications du protocole que vous implémentez au-dessus de TCP. Il doit préciser si cela se fait par des délais d'attente, des échecs d'écriture ou tout autre mécanisme. Si vous concevez un protocole, assurez-vous de concevoir un moyen de détecter la déconnexion du client, si cela est nécessaire.

-4voto

Anand Paul Points 198

La valeur de retour de la réception sera -1 si la connexion est perdue, sinon elle sera la taille du tampon.

void ReceiveStream(void *threadid)
{
    while(true)
    {
        while(ch==0)
        {
            char buffer[1024];
            int newData;
            newData = recv(thisSocket, buffer, sizeof(buffer), 0);
            if(newData>=0)
            {
                std::cout << buffer << std::endl;
            }
            else
            {
                std::cout << "Client disconnected" << std::endl;
                if (thisSocket)
                {
                    #ifdef WIN32
                        closesocket(thisSocket);
                        WSACleanup();
                    #endif
                    #ifdef LINUX
                        close(thisSocket);
                    #endif
                }
                break;
            }
        }
        ch = 1;
        StartSocket();
    }
}

2 votes

-1 n'est renvoyé qu'en cas d'erreur, pas en cas de déconnexion. J'ai vérifié sous Windows et Linux que lorsqu'un pair se déconnecte de manière non gracieuse, recv renvoie simplement un tampon rempli de zéros.

0 votes

@TekuConcept Incorrect. Il retournera -1 avec errno == ECONNRESET et cela ne fera rien du tout au tampon.

0 votes

Selon la page de manuel, vous avez raison ! Je suppose que j'ai négligé cette ligne "Des erreurs supplémentaires peuvent être générées et renvoyées par les modules de protocole sous-jacents".

-9voto

sep Points 1757

Select (avec le masque de lecture défini) reviendra avec le handle signalé, mais lorsque vous utiliserez ioctl* pour vérifier le nombre d'octets en attente de lecture, il sera égal à zéro. C'est un signe que la socket a été déconnectée.

Il s'agit d'une excellente discussion sur les différentes méthodes permettant de vérifier que le client s'est déconnecté : Stephen Cleary, Détection des connexions semi-ouvertes (abandonnées) .

* pour Windows, utilisez ioctlsocket.

0 votes

Merci ! Cette réponse m'a également été très utile :)

86 votes

C'est absolument et positivement PAS un "signe que la prise a été déconnectée". C'est un signe qu'il n'y a pas de données dans le tampon de réception de la socket. C'est un point c'est tout. Ce n'est pas du tout la même chose. L'article que vous citez pour étayer votre réponse ne mentionne même pas cette technique.

0 votes

Le socket sera signalé lorsqu'il recevra des données, mais si la somme de contrôle n'est pas vérifiée, il n'y aura plus de données dans le tampon de lecture.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X