Au hasard “Une connexion existante a dû être fermée par l'hôte distant.” après une réinitialisation TCP
J'ai deux pièces, un client et un serveur. Et j'essaie d'envoyer des données (taille > 5840 Octets) à partir du client vers le serveur, puis le serveur envoie les données en arrière. Je boucle ce un certain nombre de temps d'attente d'une seconde entre chaque temps. Parfois, le serveur crash de l'application, l'accident semble très aléatoire de l'erreur:
Exception Non Gérée: System.IO.IOException: Impossible de lire les données de la connexion de transport: Une connexion existante a dû être fermée par l'hôte distant. --->
Système.Net.Les Sockets.Exception socketexception: Une connexion existante a dû être fermée par l'hôte distant
au Système.Net.Les Sockets.Socket.Recevoir(Byte[] buffer, Int32 offset, taille Int32, SocketFlags socketFlags)
au Système.Net.Les Sockets.NetworkStream.Read(Byte[] buffer, Int32 décalage, Int32 s
ize)--- Fin de l'exception interne trace de la pile ---
au Système.Net.Les Sockets.NetworkStream.Read(Byte[] buffer, Int32 décalage, Int32 s
ize)à TCP_Server.Programme.Main(String[] args)
Code Client (C'est à l'intérieur de la boucle):
try
{
Int32 port = 13777;
using (TcpClient client = new TcpClient(ip, port))
using (NetworkStream stream = client.GetStream())
{
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
var data = GenerateData(size);
sw.Start();
//Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
//Buffer to store the response bytes.
data = new Byte[size];
//Read the first batch of the TcpServer response bytes.
Int32 bytes = stream.Read(data, 0, data.Length);
sw.Stop();
Console.WriteLine(i + ": Done transporting " + size + " bytes to and from " + ip + " time: " +
sw.ElapsedMilliseconds + " ms");
//Close everything.
stream.Close();
client.Close();
}
}
catch (ArgumentNullException e)
{
Console.WriteLine("ArgumentNullException: {0}", e);
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
sw.Reset();
Code serveur:
Byte[] bytes = new Byte[size];
//Enter the listening loop.
for (int i = 0; i < numberOfPackages; i++)
{
using (TcpClient client = server.AcceptTcpClient())
using (NetworkStream stream = client.GetStream())
{
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
//Loop to receive all the data sent by the client.
while ((stream.Read(bytes, 0, bytes.Length)) != 0)
{
//Send back a response.
stream.Write(bytes, 0, size);
}
client.GetStream().Close();
client.Close();
}
Console.WriteLine("Receive data size " + size);
}
J'ai utilisé wireshark pour surveiller le tcp des paquets envoyés et a constaté qu'un paquet TCP RST est envoyé par le client au serveur avant que le programme se bloque. Donc je suppose que le problème est que le premier n'est pas de poignées correctement.
Il n'y a pas de pare-feu entre le client et l'hôte qui n'est pas le problème.
La wireshark fichiers pour le Client et le Serveur est ici: https://www.dropbox.com/sh/ctl2chq3y2c20n7/AACgIJ8IRiclqnyOyw8sqd9La?dl=0
Donc, soit j'ai besoin de se débarrasser de la TCP RST ou j'ai besoin de mon serveur pour gérer d'une certaine façon et pas de plantage.
J'ai essayé d'utiliser plus de temps d'attente, mais ça n'aide pas.
Si les données ci-dessous 5840 Octets je ne reçois pas tout les crashs, ce que je sais de la.
Des suggestions ou des idées?
EDIT:
Merci pour les réponses que j'ai eu à travailler avec les modifications suivantes:
Serveur:
//Loop to receive all the data sent by the client.
int k = 0;
while (k < size)
{
int bytesRead = stream.Read(bytes, 0, bytes.Length);
k += bytesRead;
}
//Send back a response.
stream.Write(bytes, 0, size);
Et même lors de la réception sur le côté client. Depuis que je tiens d'abord à envoyer toutes les données et de laisser le serveur de répondre cela fonctionne pour mon application.
OriginalL'auteur TobiasW | 2015-09-10
Vous devez vous connecter pour publier un commentaire.
Deux problèmes que je vois:
size
d'octets effectivement lussize
octets. Il ne le fait pas. TCP est un protocole de streaming. Une lecture lit au moins un octet. C'est la seule garantie donnée.Je ne sais pas dans quelles circonstances exactes d'une pile TCP envoyer un de la TVD. Pourrait être due à l'impasse provoquant un dépassement de délai.
Vous n'êtes pas en avaler des exceptions, non?
Normalement, la fermeture d'une connexion effectue un arrêt à l'arrière-plan. Mais je n'en suis pas sûr à propos de ce qui se passe lorsque l'autre partie est toujours écrit à ce point. Peut-être que la réponse est que TVD est généré par le récepteur de l'écrit. Sûrement, le TCP spec permettrait de répondre à cette question. Si cette réponse est pour être digne de confiance alors, en effet, un Arrêt(Lecture)/Fermeture suivie par l'arrivée d'un d'écrire d'abord le connexion.
Fixer à la fois les questions et de faire rapport des résultats de votre recherche.
Je pense que vous ne comprenez pas le problème de blocage. Ce code au hasard de blocage. Essayer d'envoyer 100 mo et ce sera l'impasse pour vous.
Même si j'ai d'abord envoyer le tout à partir du client, le serveur reçoit tout avant de l'envoyer? Après cela, je fais attendre et de le faire tout de nouveau. Le code n'est pas utilisé pour de vrai, c'est plus un point de référence de l'application.
Le serveur échos les données, mais la mémoire tampon se remplit parce que personne ne les drains. tampons réseau sont limités en taille. Exécuter 100 MO par ce biais.
Je suis seulement en mesure d'exécuter 10000000 Octet =9.536743 (MO) en raison d'autres problèmes de mémoire. Et qui fonctionnent bien.
OriginalL'auteur usr
Je suis pas expert, mais ne pensez-vous pas que l'appel de flux.Close() sur le Client va fermer le flux pendant que le serveur est encore en train d'essayer d'écrire à
Aussi, vous voulez peut-être placer certaines données pour marquer la fin de celui-ci, de sorte que le serveur sait et arrêt de la lecture.
Soit envoyer de l'en-tête qui peut contenir des données de longueur ou l'ajout de certains de séquence unique de données pour marquer la fin de celui-ci. Dans le processus de serveur de cela pour savoir quand le serveur est censé mettre fin à la lecture. Aussi mettre en oeuvre des suggestions par usr dans d'autres réponses. Ou tout simplement travailler sur une seule voie de transfert de premier, de sorte que vous pouvez diagnostiquer le problème.
Et pour éviter les complications, vous pouvez lire et écrire sur des ports différents, si c'est faisable pour vous.
Sur la façon de marquer la fin vous pouvez lire ici http://stackoverflow.com/questions/2389756/comment-dois-je-marc-la-fin-de-un-tcp-paquet
OriginalL'auteur user2527768
J'ai résolu le même problème avec l'augmentation de la limite du cache de l'iis de l'entrée racine. vous pouvez également désactiver la mise en cache. Espérons que cela aide.
OriginalL'auteur
Nous avons eu ce problème lors de l'utilisation de HttpClient les erreurs aléatoires, comme
ou
Problème dans la Notification Explicite de Congestion, ou ECN, dans la pile TCP. Ceci est également connu comme ECN Capacité. La Notification explicite de Congestion est une extension du Protocole Internet et le Protocole de Contrôle de Transmission et est défini dans la RFC 3168. ECN permet de bout en bout de notification de congestion de réseau sans abandon de paquets.
Si ECN Fonctionnalité est activée, vous pouvez la désactiver:
Un redémarrage n'est pas nécessaire.
OriginalL'auteur Daniil Sokolyuk