2 votes

Comment le flux de réseau détecte-t-il une déconnexion

J'ai récemment commencé à étudier la programmation des sockets et j'ai écrit un serveur TCP asynchrone simple qui peut envoyer et recevoir des données de clients individuels sans problème. Voici le code simplifié :

//boucle d'acceptation

while (true)
{
   var client = await listener.AcceptTcpClientAsync();
   new AppClient(client).Start();
} 

 // et voici la méthode start dans la classe AppClient
 public async void Start()
 {
        /// TcpClient est une propriété de classe qui est dans la portée de cette méthode
       using (var stream = TcpClient.GetStream())
       {
           string message = string.Empty;
           byte[] buffer = new byte[1000];
           int bytesRead = 0;
           while (true)
           {
                try
                {
                    bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
                }         
                catch (Exception ex)
                {
                        MessageBox.Show(ex.Message);
                        break;
                 }

                 // décode le message texte simple
                 message += Encoding.UTF8.GetString(buffer, 0, bytesRead);

           }
       }
  }

il gère des milliers de connexions de manière monofil dans une seule file, mais ce qui me contrarie, c'est que peu importe comment je détruis le client (en tuant le processus et ...), la méthode ReadAsync lance immédiatement une exception qui entre en conflit avec mes pensées. (aussi loin que j'ai lu, détecter une socket déconnectée en TCP ne devrait pas être si facile)

est-ce que je fais quelque chose de mal?

1voto

Matthew Whited Points 12255

Vous devriez utiliser le .ReadAsync() avec le cancellationToken. Ensuite, changez votre boucle pour également vérifier la valeur du jeton. Lorsque vous voulez arrêter le client, vous signalez ensuite le jeton.

Vérifiez également votre variable bytesRead. Si elle retourne 0, la connexion vient de se fermer.

1voto

shekhar suman Points 4330

ce qui me contrarie, c'est que peu importe comment je détruis le client (en tuant le processus et...), la méthode ReadAsync lance immédiatement une exception

Bienvenue dans la programmation réseau (Socket). Vous devez vous familiariser avec ces exceptions car il est très courant de rencontrer des exceptions dans ce type d'applications. Ce comportement est intentionnel.

C'est votre application qui doit être développée de manière à ce que l'utilisateur final reçoive un bon message, au lieu du message des exceptions.

...la méthode ReadAsync lance immédiatement une exception, ce qui est en conflit avec mes pensées. (autant que j'ai lu, détecter une déconnexion de socket en tcp ne devrait pas être si facile)

La raison en est :

La Propriété TcpClient.Connected obtient l'état de la connexion du socket Client lors de la dernière opération I/O. Lorsqu'elle renvoie false, le socket Client n'a soit jamais été connecté, soit n'est plus connecté.

Comme la propriété Connected reflète uniquement l'état de la connexion lors de la dernière opération, vous devriez tenter d'envoyer ou de recevoir un message pour déterminer l'état actuel. Après l'échec de l'envoi du message, cette propriété ne renvoie plus true.

Notez que ce comportement est intentionnel. Vous ne pouvez pas tester de manière fiable l'état de la connexion car, entre le test et l'envoi/réception, la connexion aurait pu être perdue. Votre code doit supposer que le socket est connecté et traiter les transmissions ratées de manière élégante.

0voto

null Points 641

Il ne "détecte" pas la déconnexion, il lance une exception car .ReadAsync essaie constamment de vérifier si des données sont disponibles pour la lecture, s'il y en a, il les écrit dans le tampon. Si la longueur des données == la longueur du tampon, alors la fonction se termine. Toutes ces étapes (il y en a probablement plus) impliquent le Stream, qui est lié au socket. Ensuite, si le socket est fermé (par le code ou manuellement), le flux est fermé. Si vous essayez de faire quelque chose avec un flux fermé, une exception sera lancée.

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