Incapaz de ler os dados da conexão de transporte: uma conexão existente foi fechada à força pelo host remoto

103

Tenho um aplicativo de servidor e às vezes, quando o cliente tenta se conectar, recebo o seguinte erro:

insira a descrição da imagem aqui

NOTA: o "não foi possível obter o stream do cliente ou o login falhou" é um texto adicionado por mim na instrução catch

e a linha na qual ele para (sThread: linha 96) é:

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

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

O que pode estar causando esse problema? Observe que isso não acontece o tempo todo

Alex
fonte

Respostas:

63

Este erro geralmente significa que a máquina de destino está em execução, mas o serviço ao qual você está tentando se conectar não está disponível. (Ele parou, travou ou está ocupado com outra solicitação).

Em inglês: A conexão com a máquina (host / servidor / PC remoto em que o serviço é executado) foi feita, mas como o serviço não estava disponível em essa máquina, a máquina não sabia o que fazer com o pedido.

Se a conexão com a máquina não estiver disponível, você verá um erro diferente. Eu esqueci o que é, mas é na linha de "Serviço inacessível" ou "Indisponível".

Editar - adicionado

É possível que isso seja causado por um firewall bloqueando a porta, mas dado que você diz que é intermitente ("às vezes quando o cliente tenta se conectar"), isso é muito improvável. Eu não incluí isso originalmente porque eu havia descartado mentalmente antes de responder.

David
fonte
1
o fato é que quando eu inicio o servidor, há uns 50 clientes se conectando ao meu servidor. Eu implementei uma espécie de sinal de espera ao aceitar um cliente .. algo como while (Program.waitToFinishLoginAtClient == true && ajutor <30) {Thread.Sleep (300); ajutor ++; } client = this.tcpListener.AcceptTcpClient (); Program.waitToFinishLoginAtClient = true; ........... e Program.waitToFinishAtClient são modificados no segmento que contém o cliente
Alex
poderia essa "espera" ser o problema?
Alex
1
devo apenas deixar estar? não, espera?
Alex
1
Acho que a espera é o problema. Não sei o suficiente sobre o seu código para ter certeza, mas parece provável. Só estou curioso para saber se você construiu seu próprio serviço da "maneira mais difícil" ou se você está usando WCF ou mesmo Remoting para isso ...
David
Com base no pequeno código aqui, parece-me que o problema de "espera" poderia ser evitado se estivesse dentro de uma thread separada para cada conexão. Apenas no caso de sua suposição estar certa, aqui está um exemplo de um serviço TCP multi-thread com multi-threading que pode ajudá-lo: switchonthecode.com/tutorials/…
David
180

Recebi este erro ao chamar um serviço da web. O problema também estava relacionado à segurança do nível de transporte. Eu poderia chamar o serviço da web por meio de um projeto de site, mas ao reutilizar o mesmo código em um projeto de teste, receberia uma WebException que continha esta mensagem. Adicionar a seguinte linha antes de fazer a chamada resolveu o problema:

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

Editar

System.Net.ServicePointManager.SecurityProtocol - Esta propriedade seleciona a versão do protocolo Secure Sockets Layer (SSL) ou Transport Layer Security (TLS) para usar apenas para novas conexões que usam o esquema HTTPS (Secure Hypertext Transfer Protocol); as conexões existentes não são alteradas.

Acredito que a SecurityProtocolconfiguração seja importante durante o handshake do TLS ao selecionar a versão do protocolo.

TLS handshake - este protocolo é usado para trocar todas as informações exigidas por ambos os lados para a troca dos dados reais do aplicativo por TLS.

ClientHello - Um cliente envia uma mensagem ClientHello especificando a versão de protocolo TLS mais alta que suporta ...

ServerHello - O servidor responde com uma mensagem ServerHello, contendo a versão do protocolo escolhida ... A versão do protocolo escolhida deve ser a mais alta que o cliente e o servidor suportam. Por exemplo, se o cliente oferece suporte a TLS versão 1.1 e o servidor oferece suporte à versão 1.2, a versão 1.1 deve ser selecionada; a versão 1.2 não deve ser selecionada.

Hans Vonn
fonte
8
isso me salvou! obrigado cara. no meu depurador, estou tentando chamar um serviço https durante o teste e estava tendo o problema do OP.
Blair Holmes
6
Sabemos mais sobre como / por que isso funciona? Tenho lutado com uma chamada PostAsync e isso parece corrigir meu erro também. Que bom que funcionou, mas também gostaria de saber por quê.
Kevin Matlock
1
@HansVonn Obrigado por isso! Economizei muito tempo - em relação ao porquê de ele funcionar. É apenas limitar a versão TLS que você está usando ao se conectar.
confusedandamused de
1
Não posso acreditar que isso me pegou mais uma vez! Obrigado
Sergio A.
2
OBRIGADO! Isso estava me deixando louco.
mknopf
34

Meu cenário de caso específico era que o serviço de aplicativo do Azure tinha a versão mínima do TLS alterada para 1.2

Não sei se esse é o padrão de agora em diante, mas alterá-lo de volta para 1.0 funcionou.

Você pode acessar a configuração em "Configurações de SSL".

Hugo Hilário
fonte
7
Oh meu Deus, MUITO OBRIGADA! Estou preso nisso há muuuuito tempo e verifiquei as configurações de SSL do aplicativo da web, e o mínimo foi definido como 1,2 em vez de 1,0. Quando mudei de volta para 1.0 e reiniciei o aplicativo da web, funcionou! Muito obrigado!
Mason
1
Muito obrigado, @hugo-hilário, incrivelmente funcionou para mim também! Como diabos você conseguiu encontrar uma solução tão complicada! : D
hosjay
@hosjay foi um inferno para mim também :)
Hugo Hilário
3
Salvei meu companheiro de dia!
Nitesh
Tive este problema no meu Azure Function v2
Pieter Heemeryck,
17

Não tenho certeza de quais correções nessas postagens ajudaram, mas uma delas resolveu o problema para mim ...

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

O truque que me ajudou foi parar de usar um WebRequest e usar um HttpWebRequest. O HttpWebRequest me permite brincar com três configurações importantes:

e

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

  • ETAPA 1: desative KeepAlive
  • ETAPA 2: Defina ProtocolVersion para Version 10
  • ETAPA 3: Limitando o número de pontos de serviço
SteveC
fonte
1
Essa resposta é o que resolveu esse mesmo problema para mim. Eu desliguei 'Keep Alive' na seção Http Response Headers no IIS7
drzounds
Devo acrescentar que também tive que adicionar este código ao Reference.cs para o serviço da web que estava apresentando esse comportamento. substituição protegida System.Net.WebRequest GetWebRequest (Uri uri) {System.Net.HttpWebRequest webRequest = (System.Net.HttpWebRequest) base.GetWebRequest (uri); webRequest.KeepAlive = false; return webRequest; }
drzounds
11

As chamadas para serviços HTTPS de um de nossos servidores também geravam a exceção " Não foi possível ler os dados da conexão de transporte: uma conexão existente foi fechada à força ". O serviço HTTP, entretanto, funcionou bem. Usei o Wireshark para ver se era uma falha de handshake de TLS. Acabou sendo que o cipher suite no servidor precisava ser atualizado.

Jobrocol
fonte
Isso é o que estava acontecendo comigo. Foi enviado um certificado expirado para uma conexão SSL. A renovar o certificado e funcionou.
Guilherme de Jesus Santos
8

De acordo com as respostas de "Hans Vonn".

Adicionar a seguinte linha antes de fazer a chamada resolveu o problema:

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

Depois de adicionar o protocolo de segurança e funcionando bem, mas tenho que adicionar antes de cada chamada de API que não é saudável. Acabei de atualizar a versão do framework .net para pelo menos 4.6 e, trabalhando como esperado, não preciso adicionar antes de cada chamada de API.

Mahi Uddin
fonte
1
Muito obrigado. você fez meu dia. Pode ser útil para alguns se eu mencionar que antes disso eu também testei a desativação do firewall e a adição de ServicePointManager.ServerCertificateValidationCallback, mas não funcionou.
Tekin
5

Isso não ajudará em problemas intermitentes, mas pode ser útil para outras pessoas com um problema semelhante.

Eu tinha clonado uma VM e inicializado em uma rede diferente com um novo endereço IP, mas não alterei as ligações no IIS. O Fiddler estava me mostrando "Não é possível ler dados da conexão de transporte: uma conexão existente foi fechada à força pelo host remoto" e o IE estava me dizendo "Ativar TLS 1.0, TLS 1.1 e TLS 1.2 nas configurações avançadas". Alterar a ligação para o novo endereço IP resolveu para mim.

Jon.Mozley
fonte
2

Por algum motivo, a conexão com o servidor foi perdida. Pode ser que o servidor tenha encerrado explicitamente a conexão ou um bug no servidor fez com que ele fosse fechado inesperadamente. Ou algo entre o cliente e o servidor (um switch ou roteador) interrompeu a conexão.

Pode ser o código do servidor que causou o problema, mas pode não ser. Se você tiver acesso ao código do servidor, poderá colocar alguma depuração lá para avisar quando as conexões do cliente forem fechadas. Isso pode lhe dar alguma indicação de quando e por que as conexões estão sendo interrompidas.

No cliente, você deve escrever seu código para levar em consideração a possibilidade de falha do servidor a qualquer momento. É assim que as coisas são: conexões de rede são inerentemente não confiáveis.

Jim Mischel
fonte
2

Isso resolveu meu problema. Adicionei esta linha antes de a solicitação ser feita:

System.Net.ServicePointManager.Expect100Continue = false;

Parecia que havia um proxy no caminho do servidor que não suportava o comportamento 100-continue.

Mahdi Ataollahi
fonte
1

Eu tenho esse problema no passado. Estou usando PostgreSQL e quando executo meu programa, às vezes ele se conecta e às vezes ele lança um erro como esse.

Quando faço experiências com meu código, coloco meu código de conexão na primeira linha abaixo do formulário público. Aqui está um exemplo:

ANTES:

    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());
        }

AGORA:

    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!

        }

Acho que o programa deve primeiro ler a conexão antes de fazer qualquer coisa, não sei, me corrija se eu estiver errado. Mas, de acordo com minha pesquisa, não é um problema de código - na verdade, era da própria máquina.

Happy Coding!

Curbside Coder
fonte
1
System.Net.ServicePointManager.Expect100Continue = false;

Esse problema ocorre às vezes devido ao motivo do servidor proxy implementado no servidor web. Para ignorar o servidor proxy, colocando esta linha antes de chamar o serviço de envio.

Tahir Alvi
fonte
0

Eu tinha um aplicativo de terceiros (Fiddler) em execução para tentar ver as solicitações enviadas. Fechar este aplicativo corrigiu isso para mim

Johan Aspeling
fonte
0

Tivemos um problema muito semelhante, quando o site de um cliente estava tentando se conectar ao nosso serviço de API da Web e recebendo a mesma mensagem. Isso começou a acontecer do nada, quando não houve alterações de código ou atualizações do Windows no servidor onde o IIS estava sendo executado.

No nosso caso, descobriu-se que o site da chamada estava usando uma versão do .Net que suportava apenas TLS 1.0 e, por algum motivo, o servidor onde nosso IIS estava sendo executado parecia ter parado de aceitar chamadas TLS 1.0. Para diagnosticar isso, tivemos que habilitar explicitamente o TLS por meio do registro no servidor do IIS e, em seguida, reiniciar esse servidor. Estas são as chaves reg:

[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

Minha resposta a outra pergunta aqui tem este script PowerShell que usamos para adicionar as entradas:

NOTA: Habilitar protocolos de segurança antigos não é uma boa ideia, a resposta certa em nosso caso era fazer com que o site do cliente atualizasse seu código para usar TLS 1.2, mas as entradas de registro acima podem ajudar a diagnosticar o problema em primeiro lugar.

tomRedox
fonte
0

Isso estava acontecendo comigo porque eu tinha uma dependência recursiva em meu provedor de DI. No meu caso eu tinha:

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

A correção era apenas remover o segundo registro de serviço com escopo

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

Se você tiver um certificado https no domínio, certifique-se de ter a ligação https ao nome de domínio no IIS. No IIS -> Selecione seu domínio -> Clique em Bindings A janela de Bindings é aberta. Adicione uma ligação para https.

user2147447
fonte
0

Tive um problema semelhante e estava recebendo os seguintes erros, dependendo de qual aplicativo eu usei e se ignoramos o firewall / balanceador de carga ou não:

O handshake HTTPS para [blah] (para # 136) falhou. System.IO.IOException Não é possível ler os dados da conexão de transporte: Uma conexão existente foi fechada à força pelo host remoto

e

ReadResponse () falhou: O servidor não retornou uma resposta completa para este pedido. O servidor retornou 0 bytes.

O problema acabou sendo que o certificado de servidor SSL foi perdido e não foi instalado em alguns servidores.

cachorro mortal
fonte
0

Tente verificar se você pode estabelecer um handshake em primeiro lugar. Eu tive esse problema antes ao enviar um arquivo e só descobri que o problema era a rota inexistente quando removi o upload e verifiquei se ele pode fazer o login de acordo com os parâmetros.

Raffy
fonte
0

Para mim, era um problema onde na ligação do IIS tinha o endereço IP do servidor web. Eu mudei para usar todos os IPs não atribuídos e meu aplicativo começou a funcionar.

Shivaram Gopalakrishnan
fonte
0

Eu encontrei o erro com python clr executando consulta mdx para serviços analíticos da Microsoft usando adomd

Resolvi com a ajuda de Hans Vonn e aqui está a versão python :

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

Para quem descobrirá isso mais tarde, após o .NET versão 4.6, eu também estava tendo esse problema.

Certifique-se de verificar seu arquivo web.config para as seguintes linhas:

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

Se você estiver executando 4.6.x ou uma versão superior do .NET no servidor, certifique-se de ajustar esses valores de targetFramework para corresponder à versão da estrutura em seu servidor. Se suas versões forem inferiores a 4.6.x, eu recomendaria que você atualize o .NET e use a versão mais recente, a menos que seu código dependa de uma versão mais antiga (que, nesse caso, você deve considerar atualizá-lo).

Mudei targetFrameworks para 4.7.2 e o problema desapareceu:

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

As estruturas mais recentes resolvem esse problema usando o melhor protocolo disponível e bloqueando os inseguros ou obsoletos. Se o serviço remoto ao qual você está tentando se conectar ou ligar estiver apresentando esse erro, pode ser que eles não suportem mais os protocolos antigos.

Zachary Weber
fonte