Impossible de lire les données de la connexion de transport: une connexion existante a été fermée de force par l'hôte distant

103

J'ai une application serveur et parfois, lorsque le client essaie de se connecter, j'obtiens l'erreur suivante:

entrez la description de l'image ici

REMARQUE: le "Impossible d'obtenir le flux du client ou la connexion a échoué" est un texte que j'ai ajouté dans l'instruction catch

et la ligne à laquelle il s'arrête (sThread: ligne 96) est:

tcpClient = (TcpClient)client;
clientStream = tcpClient.GetStream();
sr = new StreamReader(clientStream);
sw = new StreamWriter(clientStream);

// line 96:                 
a = sr.ReadLine();

Quelle peut être la cause de ce problème? Notez que cela n'arrive pas tout le temps

Alex
la source

Réponses:

63

Cette erreur signifie généralement que la machine cible est en cours d'exécution, mais que le service auquel vous essayez de vous connecter n'est pas disponible. (Soit il s'est arrêté, s'est écrasé ou est occupé avec une autre demande.)

En anglais: la connexion à la machine (hôte / serveur / PC distant sur lequel le service s'exécute) a été établie mais puisque le service n'était pas disponible sur cette machine, la machine ne savait pas quoi faire avec la demande.

Si la connexion à la machine n'était pas disponible, vous verriez une erreur différente. J'oublie ce que c'est, mais c'est du genre "Service inaccessible" ou "Indisponible".

Modifier - ajouté

Il est possible que cela soit causé par un pare-feu bloquant le port, mais étant donné que vous dites que c'est intermittent ("parfois lorsque le client essaie de se connecter"), c'est très peu probable. Je n'ai pas inclus cela à l'origine parce que je l'avais exclu mentalement avant de répondre.

David
la source
1
le fait est que lorsque je démarre le serveur, il y a environ 50 clients qui se connectent à mon serveur. J'ai implémenté une sorte de signal d'attente lors de l'acceptation d'un client .. quelque chose comme while (Program.waitToFinishLoginAtClient == true && ajutor <30) {Thread.Sleep (300); ajutor ++; } client = this.tcpListener.AcceptTcpClient (); Program.waitToFinishLoginAtClient = true; ........... et Program.waitToFinishAtClient est modifié dans le thread qui contient le client
Alex
cela pourrait-il être le problème?
Alex
1
devrais-je juste laisser faire? non attends ?
Alex
1
Je pense que l'attente est le problème. Je ne connais pas suffisamment votre code pour être sûr, mais cela semble probable. Je suis simplement curieux de savoir si vous avez construit votre propre service à la «dure» ou si vous utilisez WCF ou même Remoting pour cela ...
David
Sur la base du peu de code ici, il me semble que le problème «d'attente» pourrait être évité s'il était à l'intérieur d'un thread séparé pour chaque connexion. Juste au cas où cette supposition serait juste, voici un exemple de service TCP multi-thread avec multi-threading qui peut vous aider: switchonthecode.com/tutorials
David
180

J'ai reçu cette erreur lors de l'appel d'un service Web. Le problème était également lié à la sécurité au niveau du transport. Je pourrais appeler le service Web via un projet de site Web, mais lors de la réutilisation du même code dans un projet de test, j'obtiendrais une WebException contenant ce message. L'ajout de la ligne suivante avant de passer l'appel a résolu le problème:

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

Éditer

System.Net.ServicePointManager.SecurityProtocol - Cette propriété sélectionne la version du protocole Secure Sockets Layer (SSL) ou Transport Layer Security (TLS) à utiliser pour les nouvelles connexions qui utilisent le schéma HTTPS (Secure Hypertext Transfer Protocol) uniquement; les connexions existantes ne sont pas modifiées.

Je crois que la SecurityProtocolconfiguration est importante lors de la négociation TLS lors de la sélection de la version du protocole.

Prise de contact TLS - Ce protocole est utilisé pour échanger toutes les informations requises par les deux côtés pour l'échange des données d'application réelles par TLS.

ClientHello - Un client envoie un message ClientHello spécifiant la version de protocole TLS la plus élevée qu'il prend en charge ...

ServerHello - Le serveur répond avec un message ServerHello, contenant la version de protocole choisie ... La version de protocole choisie doit être la plus élevée prise en charge par le client et le serveur. Par exemple, si le client prend en charge la version 1.1 de TLS et le serveur prend en charge la version 1.2, la version 1.1 doit être sélectionnée; la version 1.2 ne doit pas être sélectionnée.

Hans Vonn
la source
8
cela m'a sauvé! Merci mec. dans mon débogueur, j'essaie d'appeler un service https pendant le test et j'avais le problème que l'OP avait.
Blair Holmes
6
En savons-nous plus sur comment / pourquoi cela fonctionne? J'ai eu du mal avec un appel PostAsync et cela semble aussi corriger mon erreur. Heureux que cela ait fonctionné, mais j'aimerais aussi savoir pourquoi.
Kevin Matlock
1
@HansVonn Merci pour cela! Cela m'a fait gagner beaucoup de temps - En ce qui concerne les raisons pour lesquelles cela fonctionne, cela limite simplement la version TLS que vous utilisez lorsque vous vous connectez.
confusedandamused
1
Je ne peux pas croire que ça m'a encore une fois! Merci
Sergio A.
2
MERCI! Cela me rendait fou.
mknopf
34

Mon scénario de cas spécifique était que le service d'application Azure avait la version TLS minimale modifiée en 1.2

Je ne sais pas si c'est la valeur par défaut à partir de maintenant, mais le remettre à 1.0 l'a fait fonctionner.

Vous pouvez accéder au paramètre dans "Paramètres SSL".

Hugo Hilário
la source
7
Oh mon dieu MERCI BEAUCOUP! Cela fait tellement longtemps que je suis coincé et j'ai vérifié les paramètres SSL de l'application Web, et le minimum a été défini sur 1,2 au lieu de 1,0. Lorsque je l'ai changé en 1.0 et que j'ai redémarré l'application Web, cela a fonctionné! Merci beaucoup!
Mason
1
Merci beaucoup, @ hugo-hilário, étonnamment, cela a fonctionné pour moi aussi! Comment diable avez-vous réussi à trouver une solution aussi délicate! : D
hosjay
@hosjay c'était un enfer pour moi aussi :)
Hugo Hilário
3
A sauvé mon compagnon de jour!
Nitesh
J'ai eu ce problème pour ma fonction Azure v2
Pieter Heemeryck
17

Je ne sais pas lequel des correctifs de ces articles de blog a aidé, mais l'un d'eux a résolu ce problème pour moi ...

http://briancaos.wordpress.com/2012/07/06/unable-to-read-data-from-the-transport-connection-the-connection-was-closed/

L'astuce qui m'a aidé a été d'arrêter d'utiliser un WebRequest et d'utiliser un HttpWebRequest à la place. Le HttpWebRequest me permet de jouer avec 3 paramètres importants:

et

http://briancaos.wordpress.com/2012/06/15/an-existing-connection-was-forcably-closed-by-the-remote-host/

  • ÉTAPE 1: Désactivez KeepAlive
  • ÉTAPE 2: définissez ProtocolVersion sur Version10
  • ÉTAPE 3: Limitation du nombre de points de service
SteveC
la source
1
Cette réponse est ce qui a résolu ce même problème pour moi. J'ai désactivé `` Keep Alive '' dans la section Http Response Headers dans IIS7
drzounds
Je dois ajouter que j'ai également dû ajouter ce code au Reference.cs pour le service Web qui avait ce comportement. remplacement protégé System.Net.WebRequest GetWebRequest (Uri uri) {System.Net.HttpWebRequest webRequest = (System.Net.HttpWebRequest) base.GetWebRequest (uri); webRequest.KeepAlive = false; return webRequest; }
drzounds le
11

Les appels aux services HTTPS depuis l'un de nos serveurs lançaient également l' exception « Impossible de lire les données de la connexion de transport: une connexion existante a été fermée de force ». Le service HTTP, cependant, fonctionnait bien. Utilisé Wireshark pour voir qu'il s'agissait d'un échec de négociation TLS. Finalement, la suite de chiffrement sur le serveur devait être mise à jour.

Jobrocol
la source
C'est ce qui m'arrivait. A a été envoyé un certificat expiré à une connexion SSL. A renouveler le certificat et travaillé.
Guilherme de Jesus Santos
8

Selon les réponses de "Hans Vonn".

L'ajout de la ligne suivante avant de passer l'appel a résolu le problème:

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

Après avoir ajouté le protocole de sécurité et fonctionné correctement, je dois ajouter avant chaque appel d'API qui n'est pas sain. Je viens de mettre à niveau la version du framework .net au moins 4.6 et travailler comme prévu ne nécessite pas d'ajouter avant chaque appel d'API.

Mahi Uddin
la source
1
Merci beaucoup. tu as fait ma journée. Cela pourrait être utile pour certains si je mentionne qu'avant cela, j'ai également testé la désactivation du pare-feu et l'ajout de ServicePointManager.ServerCertificateValidationCallback mais cela n'a pas fonctionné.
Tekin
5

Cela n'aidera pas pour les problèmes intermittents, mais peut être utile pour d'autres personnes ayant un problème similaire.

J'avais cloné une machine virtuelle et l'ai démarrée sur un réseau différent avec une nouvelle adresse IP mais je n'ai pas changé les liaisons dans IIS. Fiddler me montrait "Impossible de lire les données de la connexion de transport: une connexion existante a été fermée de force par l'hôte distant" et IE me disait "Activez TLS 1.0, TLS 1.1 et TLS 1.2 dans les paramètres avancés". Changer la liaison avec la nouvelle adresse IP l'a résolu pour moi.

Jon.Mozley
la source
2

Pour une raison quelconque, la connexion au serveur a été perdue. Il se peut que le serveur ait explicitement fermé la connexion ou qu'un bogue sur le serveur ait provoqué sa fermeture inopinée. Ou quelque chose entre le client et le serveur (un commutateur ou un routeur) a interrompu la connexion.

C'est peut-être le code serveur qui a causé le problème, mais ce n'est peut-être pas le cas. Si vous avez accès au code du serveur, vous pouvez y mettre du débogage pour vous dire quand les connexions client sont fermées. Cela peut vous indiquer quand et pourquoi les connexions sont interrompues.

Sur le client, vous devez écrire votre code pour prendre en compte la possibilité de défaillance du serveur à tout moment. C'est comme ça: les connexions réseau sont intrinsèquement peu fiables.

Jim Mischel
la source
2

Cela a résolu mon problème. J'ai ajouté cette ligne avant que la demande ne soit faite:

System.Net.ServicePointManager.Expect100Continue = false;

Il semblait qu'il y avait un proxy sur le chemin du serveur qui ne prenait pas en charge le comportement 100-continue.

Mahdi Ataollahi
la source
1

J'ai eu ce problème dans le passé. J'utilise PostgreSQL et quand je lance mon programme, parfois il se connecte et parfois il génère une erreur comme celle-là.

Lorsque j'expérimente mon code, je mets mon code de connexion à la toute première ligne sous le formulaire public. Voici un exemple:

AVANT:

    public Form1()
        {
        //HERE LIES SOME CODES FOR RESIZING MY CONTROLS DURING RUNTIME
        //CODE
        //CODE AGAIN
        //ANOTHER CODE
        //CODE NA NAMAN
        //CODE PA RIN!





        //Connect to Database to generate auto number
        NpgsqlConnection iConnect = new NpgsqlConnection("Server=localhost;Port=5432;User ID=postgres;Password=pass;Database=DB");
        iConnect.Open();
        NpgsqlCommand iQuery = new NpgsqlCommand("Select * from table1", iConnect);
        NpgsqlDataReader iRead = iQuery.ExecuteReader();
        NpgsqlDataAdapter iAdapter = new NpgsqlDataAdapter(iQuery);

        DataSet iDataSet = new DataSet();
        iAdapter.Fill(iDataSet, "ID");

        MessageBox.Show(iDataSet.Tables["ID"].Rows.Count.ToString());
        }

MAINTENANT:

    public Form1()
        {
        //Connect to Database to generate auto number
        NpgsqlConnection iConnect = new NpgsqlConnection("Server=localhost;Port=5432;User ID=postgres;Password=pass;Database=DB");
        iConnect.Open();
        NpgsqlCommand iQuery = new NpgsqlCommand("Select * from table1", iConnect);
        NpgsqlDataReader iRead = iQuery.ExecuteReader();
        NpgsqlDataAdapter iAdapter = new NpgsqlDataAdapter(iQuery);

        DataSet iDataSet = new DataSet();
        iAdapter.Fill(iDataSet, "ID");

        MessageBox.Show(iDataSet.Tables["ID"].Rows.Count.ToString());





        //HERE LIES SOME CODES FOR RESIZING MY CONTROLS DURING RUNTIME
        //CODE
        //CODE AGAIN
        //ANOTHER CODE
        //CODE NA NAMAN
        //CODE PA RIN!

        }

Je pense que le programme doit d'abord lire la connexion avant de faire quoi que ce soit, je ne sais pas, corrigez-moi si je me trompe. Mais d'après mes recherches, ce n'est pas un problème de code - c'était en fait de la machine elle-même.

Bon codage!

Codeur de trottoir
la source
1
System.Net.ServicePointManager.Expect100Continue = false;

Ce problème se produit parfois en raison du serveur proxy implémenté sur le serveur Web. Pour contourner le serveur proxy en mettant cette ligne avant d'appeler le service d'envoi.

Tahir Alvi
la source
0

J'avais une application tierce (Fiddler) en cours d'exécution pour essayer de voir les demandes envoyées. La fermeture de cette application l'a corrigé pour moi

Johan Aspeling
la source
0

Nous avons eu un problème très similaire où le site Web d'un client essayait de se connecter à notre service API Web et recevait le même message. Cela a commencé à se produire complètement à l'improviste lorsqu'il n'y avait pas eu de modifications de code ou de mises à jour Windows sur le serveur sur lequel IIS s'exécutait.

Dans notre cas, il s'est avéré que le site Web appelant utilisait une version de .Net qui ne prenait en charge que TLS 1.0 et pour une raison quelconque, le serveur sur lequel notre IIS fonctionnait arrêté semblait avoir cessé d'accepter les appels TLS 1.0. Pour diagnostiquer que nous devions activer explicitement TLS via le registre sur le serveur IIS, puis redémarrer ce serveur. Ce sont les clés de registre:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
    1.0\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
    1.0\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
    1.1\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
    1.1\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
    1.2\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
    1.2\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

If that doesn't do it, you could also experiment with adding the entry for SSL 2.0:


    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client]
    "DisabledByDefault"=dword:00000000
    "Enabled"=dword:00000001

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server]
    "DisabledByDefault"=dword:00000000
    "Enabled"=dword:00000001

Ma réponse à une autre question ici a ce script PowerShell que nous avons utilisé pour ajouter les entrées:

REMARQUE: l' activation des anciens protocoles de sécurité n'est pas une bonne idée, la bonne réponse dans notre cas était de demander au site Web du client de mettre à jour son code pour utiliser TLS 1.2, mais les entrées de registre ci-dessus peuvent aider à diagnostiquer le problème en premier lieu.

tomRedox
la source
0

La raison pour laquelle cela m'arrivait était que j'avais une dépendance récursive dans mon fournisseur de DI. Dans mon cas, j'avais:

services.AddScoped(provider => new CfDbContext(builder.Options));
services.AddScoped(provider => provider.GetService<CfDbContext>());

Le correctif consistait simplement à supprimer le deuxième enregistrement de service à portée

services.AddScoped(provider => new CfDbContext(builder.Options));
Madison Haynie
la source
0

Si vous disposez d'un certificat https sur le domaine, assurez-vous que vous disposez de la liaison https avec le nom de domaine dans IIS. Dans IIS -> Sélectionnez votre domaine -> Cliquez sur Liaisons La fenêtre des liaisons de site s'ouvre. Ajoutez une liaison pour https.

user2147447
la source
0

J'ai eu un problème similaire et obtenait les erreurs suivantes en fonction de l'application que j'ai utilisée et si nous avons contourné le pare-feu / l'équilibreur de charge ou non:

La négociation HTTPS avec [bla] (pour # 136) a échoué. System.IO.IOException Impossible de lire les données à partir de la connexion de transport: une connexion existante a été fermée de force par l'hôte distant

et

ReadResponse () a échoué: le serveur n'a pas renvoyé de réponse complète pour cette demande. Le serveur a renvoyé 0 octet.

Le problème s'est avéré être que le certificat de serveur SSL a été manqué et n'a pas été installé sur quelques serveurs.

chien mortel
la source
0

Essayez de vérifier si vous pouvez établir une poignée de main en premier lieu. J'ai eu ce problème avant lors du téléchargement d'un fichier et j'ai seulement compris que le problème était la route inexistante lorsque j'ai supprimé le téléchargement et vérifié s'il pouvait se connecter compte tenu des paramètres.

Raffy
la source
0

Pour moi, c'était un problème où dans la liaison IIS, il avait l'adresse IP du serveur Web. Je l'ai changé pour utiliser toutes les adresses IP non attribuées et mon application a commencé à fonctionner.

Shivaram Gopalakrishnan
la source
0

J'ai rencontré l'erreur avec python clr exécutant une requête mdx sur les services d'analyse Microsoft à l'aide d'adomd

Je l'ai résolu avec l'aide de Hans Vonn et voici la version python :

clr.AddReference("System.Net")
from System.Net import ServicePointManager, SecurityProtocolType 
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls
Peter Kazmir
la source
0

Pour ceux qui pourraient le trouver plus tard, après la version 4.6 de .NET, je rencontrais également ce problème.

Assurez-vous que vous vérifiez votre fichier web.config pour les lignes suivantes:

<compilation debug="true" targetFramework="4.5">
...
<httpRuntime targetFramework="4.5" />

Si vous exécutez 4.6.x ou une version supérieure de .NET sur le serveur, assurez-vous d'ajuster ces valeurs targetFramework pour qu'elles correspondent à la version de l'infrastructure sur votre serveur. Si vos versions lisent moins de 4.6.x, je vous recommande de mettre à niveau .NET et d'utiliser la version la plus récente à moins que votre code ne dépende d'une version plus ancienne (qui, dans ce cas, vous devriez envisager de la mettre à jour).

J'ai changé le targetFrameworks en 4.7.2 et le problème a disparu:

<compilation debug="true" targetFramework="4.7.2">
...
<httpRuntime targetFramework="4.7.2" />

Les nouveaux frameworks résolvent ce problème en utilisant le meilleur protocole disponible et en bloquant les protocoles non sécurisés ou obsolètes. Si le service distant auquel vous essayez de vous connecter ou d'appeler donne cette erreur, il se peut qu'il ne prenne plus en charge les anciens protocoles.

Zachary Weber
la source