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

159

Je travaille avec une application commerciale qui lance une SocketException avec le message,

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

Cela se produit avec une connexion socket entre le client et le serveur. La connexion est bien vivante et des tas de données sont transférées, mais elles se déconnectent alors de nulle part.

Est-ce que quelqu'un a déjà vu ça? Quelles pourraient être les causes? Je peux en quelque sorte deviner quelques causes, mais y a-t-il également un moyen d'en ajouter plus dans ce code pour déterminer quelle pourrait être la cause?

Tous les commentaires / idées sont les bienvenus.

... Le dernier ...

J'ai une journalisation à partir d'un traçage .NET,

System.Net.Sockets Verbose: 0 : [8188] Socket#30180123::Send() DateTime=2010-04-07T20:49:48.6317500Z

System.Net.Sockets Error: 0 : [8188] Exception in the Socket#30180123::Send - An existing connection was forcibly closed by the remote host DateTime=2010-04-07T20:49:48.6317500Z 

System.Net.Sockets Verbose: 0 : [8188] Exiting Socket#30180123::Send() -> 0#0

Sur la base d'autres parties de la journalisation, j'ai vu le fait qu'il dit «0 # 0» signifie qu'un paquet de 0 octets de longueur est envoyé. Mais qu'est-ce que cela signifie réellement?

L'une des deux possibilités se présente, et je ne sais pas laquelle,

1) La connexion est en cours de fermeture, mais les données sont ensuite écrites sur le socket, créant ainsi l'exception ci-dessus. Le 0 # 0 signifie simplement que rien n'a été envoyé car le socket était déjà fermé.

2) La connexion est toujours ouverte et un paquet de zéro octet est envoyé (c'est-à-dire que le code a un bogue) et le 0 # 0 signifie qu'un paquet de zéro octet tente d'être envoyé.

Qu'est-ce que tu en penses? Ce n'est peut-être pas concluant, je suppose, mais peut-être que quelqu'un d'autre a vu ce genre de chose?

peter
la source
Juste une mise à jour. Il semble que WireShark ne va pas le couper dans ce cas en raison de la configuration de notre réseau. Mais j'espère que j'essaierai ceci, blogs.msdn.com/dgorti/archive/2005/09/18/471003.aspx qui trace en utilisant .NET qui devrait produire des fichiers journaux. Je vous tiendrai au courant ...
peter
1
comcast est également connu pour envoyer des paquets "zéro" usurpés avec un faux identifiant pour gâcher le trafic p2p ---

Réponses:

98

Cela signifie généralement que le côté distant a fermé la connexion (généralement en envoyant un RSTpaquet TCP / IP ). Si vous travaillez avec une application tierce, les causes probables sont:

  • Vous envoyez des données mal formées à l'application (ce qui peut inclure l'envoi d'une requête HTTPS à un serveur HTTP)
  • La liaison réseau entre le client et le serveur est en panne pour une raison quelconque
  • Vous avez déclenché un bogue dans l'application tierce qui l'a fait planter
  • L'application tierce a épuisé les ressources système

Il est probable que le premier cas soit ce qui se passe.

Vous pouvez lancer Wireshark pour voir exactement ce qui se passe sur le fil pour affiner le problème.

Sans informations plus spécifiques, il est peu probable que quelqu'un ici puisse vraiment vous aider.

RarrRarrRarr
la source
2
Génial. Merci. L'autre chose à propos de WireShark. Il recueille tellement de données, comment pourrais-je filtrer quelque chose comme ça? Si WireShark montre quelque chose, je pourrais le poster ici plus tard ...
Peter
4
Vous devriez être en mesure de filtrer le vidage Wireshark par adresse IP et numéro de port, au moins. Après cela, il est probablement plus utile de regarder la fin du flux (là où quelque chose s'est mal passé) et de travailler en arrière jusqu'à ce que vous puissiez repérer où les choses se sont gâchées. Selon la complexité du protocole impliqué, cela peut être vraiment facile à presque impossible ...
RarrRarrRarr
4
Existe-t-il une source pour les éléments à puces, ou la réponse du joueur ci-dessous a-t-elle simplement copié votre liste?
Zack
7
Veuillez noter que «envoyer des données mal formées» peut signifier envoyer une httpsrequête à un httpserveur et probablement vice versa.
AXMIM
2
Dans mon cas, j'obtenais cette exception uniquement lors de l'appel d'une API lors de l'exécution d'une application localement. Aucun problème dans les environnements de développement, de contrôle qualité ou de production. Le correctif? Utilisation de http au lieu de https localement. Nous pensons que cela peut être lié à un équilibreur de charge. Mais nous venons de mettre à jour nos web.configs dev, qa et prod avec des transformations pour https. Problème résolu.
Kershaw
82

L'utilisation de TLS 1.2 a résolu cette erreur.
Vous pouvez forcer votre application à utiliser TLS 1.2 avec ceci (assurez-vous de l'exécuter avant d'appeler votre service):

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 

Une autre solution:
activez une cryptographie forte sur votre machine ou serveur local afin d'utiliser TLS1.2 car par défaut, il est désactivé, donc seul TLS1.0 est utilisé.
Pour activer la cryptographie forte, exécutez ces commandes dans PowerShell avec des privilèges d'administrateur:

Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord 

Vous devez redémarrer votre ordinateur pour que ces modifications prennent effet.

Willmaz
la source
1
Vous pouvez ajouter plusieurs valeurs ensemble pour prendre en charge plusieurs protocoles. Donc, pour tout prendre en charge, de SSL3 à TLS1.2, définissez SecurityProtocol = (SecurityProtocolType) 4080.
Abacus
29

Ce n'est pas un bogue dans votre code. Il provient de l'implémentation Socket de .Net. Si vous utilisez l'implémentation surchargée d'EndReceive comme ci-dessous, vous n'obtiendrez pas cette exception.

    SocketError errorCode;
    int nBytesRec = socket.EndReceive(ar, out errorCode);
    if (errorCode != SocketError.Success)
    {
        nBytesRec = 0;
    }
Cagatay
la source
1
Cela vient du système d'exploitation, et finalement du pair. Des explications supplémentaires sont nécessaires sur l'allégation selon laquelle il s'agit d'un bogue logiciel.
Marquis of Lorne
5
+1. Dans mon programme C #, je me suis cogné la tête pour savoir pourquoi EndReceivelançait une exception lorsqu'il y a une résiliation de client gracieuse. Je ne savais pas que c'était par conception. Je pense que sa mauvaise conception est de lancer une exception dans les flux de code normaux. Merci à Dieu pour la méthode surchargée.
Pavan Manjunath
2
@MSaudi Ceci utilise un appel asynchrone, assurez-vous de comprendre que votre code ne s'arrêtera pas pendant le traitement des données renvoyées. L'exemple utilise msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx . Fondamentalement, vous devez avoir une StateObjectclasse avec public byte[] buffer = new byte[1024], public Socket socket;et appeler une fonction appelée Receive(Socket s), qui fait StateObject so = new StateObject(); so.socket = s; s.BeginReceive(so.buffer, 0, 256, 0, new AsyncCallback(ReceiveCallback), so); et dans void ReceiveCallback(IAsyncResult ar)vous appelez ce code, ci-dessus.
vapcguy
2
@cagatay Bien qu'il offre une solution, je n'ai jamais vu la valeur des méthodes asynchrones où vous devez savoir tout de suite ce qui revient après avoir fait votre Sendavant de pouvoir faire autre chose.
vapcguy
3
En fait, j'ai trouvé que cette méthode n'est pas infaillible. Cela peut également provoquer l'erreur de l'OP: stackoverflow.com/questions/17790612/…
vapcguy
10

Solution simple pour ce problème ennuyeux courant:

Allez simplement dans votre fichier " .context.cs" (situé sous " .context.tt" qui se trouve sous votre fichier "* .edmx").

Ensuite, ajoutez cette ligne à votre constructeur:

public DBEntities() 
        : base("name=DBEntities") 
    { 
        this.Configuration.ProxyCreationEnabled = false; // ADD THIS LINE !
    }

espérons que cela est utile.

ayheber
la source
@Esi où mettre ça? et pas de type de retour ??
Khalil Khalaf
2
@FirstStep: Parce que c'est un constructeur.
Nikhil Agrawal
3
Cela aide uniquement ceux qui utilisent Entity Framework qui rencontrent le problème, pas ceux qui font une simple socket.Send(x); byte[] buffer = new byte[1]; socket.Receive(buffer, 0, 1, 0);lecture des octets retournés, ce qui était le problème de l'OP.
vapcguy
si utiliser ENTITY FRAMEWORKuniquement cette solution fonctionne !!! seulement ça ! merci bro :)
Rao Hammas
9

Eu le même bug. En fait, cela fonctionnait au cas où le trafic serait envoyé à l'aide d'un proxy (un violon dans mon cas). Mise à jour du framework .NET de 4.5.2 à> = 4.6 et maintenant tout fonctionne correctement. La demande réelle était:
new WebClient().DownloadData("URL");
L'exception était:

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

0x49D1
la source
5
C'était une façon de résoudre les choses pour moi. Il était en fait lié à la version de TLS .NET utilisée par défaut. 4.5.2 et versions antérieures utilisaient TLS 1.0, tandis que 4.6 et versions ultérieures sont plus intelligentes pour autoriser 1.1 et 1.2. Cela a également été prouvable en supprimant l'exigence TLS sur le serveur à 1.0, ce qui a également résolu le problème.
HotN
4

J'ai cette exception en raison de la référence circulaire dans l'entité. Dans l'entité qui ressemble à

public class Catalog
{
    public int Id { get; set; }
    public int ParentId { get; set; }
    public Catalog Parent { get; set; }
    public ICollection<Catalog> ChildCatalogs { get; set; }
}

J'ai ajouté [IgnoreDataMemberAttribute] à la propriété Parent. Et cela a résolu le problème.

Bazaleev Nikolay
la source
2

Si vous utilisez un service .Net 4.5.2

Pour moi, le problème a été aggravé parce que l'appel était en cours d'exécution dans un service .Net 4.5.2. J'ai suivi la suggestion de @willmaz mais j'ai eu une nouvelle erreur.

En exécutant le service avec la journalisation activée, j'ai vu que l'établissement de liaison avec le site cible lancerait ok (et enverrait le jeton du porteur) mais à l'étape suivante pour traiter l'appel de publication, il semblerait que le jeton d'authentification soit abandonné et le site répondre avec Unauthorized.

Il s'est avéré que les informations d'identification du pool de services n'avaient pas le droit de modifier TLS (?) Et lorsque j'ai mis mon compte d'administrateur local dans le pool, tout fonctionnait.

ΩmegaMan
la source
2

Pour quiconque obtient cette exception lors de la lecture des données du flux, cela peut aider. J'obtenais cette exception lors de la lecture du HttpResponseMessage dans une boucle comme celle-ci:

using (var remoteStream = await response.Content.ReadAsStreamAsync())
using (var content = File.Create(DownloadPath))
{
    var buffer = new byte[1024];
    int read;

    while ((read = await remoteStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
    {
        await content.WriteAsync(buffer, 0, read);
        await content.FlushAsync();
    }
}

Après un certain temps, j'ai découvert que le coupable était la taille de la mémoire tampon, qui était trop petite et ne fonctionnait pas bien avec ma faible instance Azure. Ce qui a aidé, c'est de changer le code en:

using (Stream remoteStream = await response.Content.ReadAsStreamAsync())
using (FileStream content = File.Create(DownloadPath))
{
    await remoteStream.CopyToAsync(content);
}

La méthode CopyTo () a une taille de tampon par défaut de 81920. La plus grande mémoire tampon a accéléré le processus et les erreurs se sont arrêtées immédiatement, probablement parce que les vitesses de téléchargement globales ont augmenté. Mais pourquoi la vitesse de téléchargement serait-elle importante pour éviter cette erreur?

Il est possible que vous soyez déconnecté du serveur car les vitesses de téléchargement chutent en dessous du seuil minimum que le serveur est configuré pour autoriser. Par exemple, si l'application à partir de laquelle vous téléchargez le fichier est hébergée sur IIS, cela peut être un problème avec la configuration de http.sys:

"Http.sys est la pile de protocoles http qu'IIS utilise pour effectuer la communication http avec les clients. Il dispose d'un minuteur appelé MinBytesPerSecond qui est responsable de la suppression d'une connexion si son taux de transfert tombe en dessous d'un seuil de kb / s. Par défaut, ce seuil est réglé sur 240 kb / s. "

Le problème est décrit dans cet ancien article de blog de l'équipe de développement TFS et concerne spécifiquement IIS, mais peut vous orienter dans la bonne direction. Il mentionne également un ancien bogue lié à cet attribut http.sys: lien

Si vous utilisez les services d'application Azure et que l'augmentation de la taille de la mémoire tampon n'élimine pas le problème, essayez également de mettre à l'échelle votre ordinateur. Vous recevrez plus de ressources, y compris la bande passante de connexion.

Andrej Lucansky
la source
0

J'ai eu le même problème et j'ai finalement réussi à le résoudre. Dans mon cas, le port auquel le client envoie la demande n'avait pas de liaison de certificat SSL. J'ai donc résolu le problème en liant un certificat SSL au port côté serveur. Une fois que cela a été fait, cette exception a disparu.

iefgnoix
la source
-1

Cette erreur s'est produite dans mon application avec le protocole CIP chaque fois que je n'ai pas envoyé ou reçu de données en moins de 10 secondes.

Cela a été causé par l'utilisation de la méthode ouverte avant. Vous pouvez éviter cela en travaillant avec une autre méthode ou en installant un taux de mise à jour inférieur aux 10 qui maintiennent votre connexion avant-ouverte.

Belekz
la source