Uma conexão existente foi fechada à força pelo host remoto

159

Estou trabalhando com um aplicativo comercial que está lançando uma SocketException com a mensagem

Uma conexão existente foi fechada à força pelo host remoto

Isso acontece com uma conexão de soquete entre cliente e servidor. A conexão está ativa e bem, e montes de dados estão sendo transferidos, mas depois são desconectados do nada.

alguém viu isso antes? Quais poderiam ser as causas? Posso adivinhar algumas causas, mas também há alguma maneira de adicionar mais esse código para descobrir qual poderia ser a causa?

Quaisquer comentários / idéias são bem-vindos.

... O mais recente ...

Eu tenho alguns logs de algum rastreamento .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

Com base em outras partes do log, vi o fato de que diz '0 # 0' significa que um pacote com 0 bytes de comprimento está sendo enviado. Mas o que isso realmente significa?

Uma das duas possibilidades está ocorrendo, e não tenho certeza de qual,

1) A conexão está sendo fechada, mas os dados estão sendo gravados no soquete, criando a exceção acima. O 0 # 0 significa simplesmente que nada foi enviado porque o soquete já estava fechado.

2) A conexão ainda está aberta e um pacote de zero bytes está sendo enviado (ou seja, o código possui um bug) e 0 # 0 significa que um pacote de zero bytes está tentando ser enviado.

O que você acha? Pode ser inconclusivo, eu acho, mas talvez alguém tenha visto esse tipo de coisa?

Peter
fonte
Apenas uma atualização. Parece que o wireshark não vai funcionar nesse caso por causa da nossa configuração de rede. Mas espero tentar isso, blogs.msdn.com/dgorti/archive/2005/09/18/471003.aspx , que está rastreando usando o .NET, que deve produzir alguns arquivos de log. Vou mantê-lo informado ...
Peter
1
Comcast também é conhecido por enviar pacotes "zero" falsificado com identidade falsa para mexer com o tráfego P2P ---

Respostas:

98

Isso geralmente significa que o lado remoto fechou a conexão (geralmente enviando um RSTpacote TCP / IP ). Se você estiver trabalhando com um aplicativo de terceiros, as causas prováveis ​​são:

  • Você está enviando dados malformados para o aplicativo (o que pode incluir o envio de uma solicitação HTTPS para um servidor HTTP)
  • O link de rede entre o cliente e o servidor está inoperante por algum motivo
  • Você acionou um bug no aplicativo de terceiros que causou o travamento
  • O aplicativo de terceiros esgotou os recursos do sistema

É provável que o primeiro caso seja o que está acontecendo.

Você pode ativar o Wireshark para ver exatamente o que está acontecendo no fio para diminuir o problema.

Sem informações mais específicas, é improvável que alguém aqui possa realmente ajudá-lo.

RarrRarrRarr
fonte
2
Ótimo. Obrigado. A outra coisa sobre wireshark. Ele coleta tantos dados, como eu seria capaz de filtrar algo assim? Se mostra Wireshark até algo que eu possa publicá-la aqui mais tarde ...
Peter
4
Você deve conseguir filtrar o despejo do Wireshark pelo endereço IP e pelo número da porta, pelo menos. Depois disso, é provavelmente mais útil olhar para o final do fluxo (onde algo deu errado) e trabalhar para trás até que você possa identificar onde as coisas ficam estragadas. Dependendo da complexidade do protocolo envolvido, ele pode ser muito fácil a quase impossível ...
RarrRarrRarr
4
Existe uma fonte para os itens com marcadores ou a resposta do jogador abaixo acabou de copiar sua lista?
Zack
7
Observe que "enviar dados malformados" pode significar enviar uma httpssolicitação para um httpservidor e provavelmente vice-versa.
AXMIM 25/09
2
No meu caso, eu estava recebendo essa exceção apenas ao chamar uma API ao executar o aplicativo localmente. Sem problemas nos ambientes dev, qa ou prod. O conserto? Usando http em vez de https localmente. Achamos que isso pode estar relacionado a um balanceador de carga. Mas acabamos de atualizar nosso dev, qa e prod web.configs com transformações para https. Problema resolvido.
Kershaw #
82

O uso do TLS 1.2 resolveu esse erro.
Você pode forçar seu aplicativo usando o TLS 1.2 com isso (certifique-se de executá-lo antes de ligar para o serviço):

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 

Outra solução:
ative criptografia forte em sua máquina ou servidor local para usar o TLS1.2 porque, por padrão, ele está desativado para que apenas o TLS1.0 seja usado.
Para habilitar criptografia forte, execute estes comandos no PowerShell com privilégios de administrador:

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 

Você precisa reiniciar o computador para que essas alterações entrem em vigor.

willmaz
fonte
1
Você pode adicionar vários valores juntos para suportar vários protocolos. Portanto, para oferecer suporte a tudo, do SSL3 ao TLS1.2, configure SecurityProtocol = (SecurityProtocolType) 4080.
Abacus
29

Este não é um erro no seu código. É proveniente da implementação do .Net's Socket. Se você usar a implementação sobrecarregada do EndReceive como abaixo, você não receberá essa exceção.

    SocketError errorCode;
    int nBytesRec = socket.EndReceive(ar, out errorCode);
    if (errorCode != SocketError.Success)
    {
        nBytesRec = 0;
    }
cagatay
fonte
1
Isso vem do sistema operacional e, finalmente, do mesmo nível. É necessária mais explicação sobre a alegação de que é um bug do software.
Marquês de Lorne
5
+1. No meu programa em C #, eu estava me perguntando por que EndReceiveestá lançando uma exceção quando há um encerramento normal do cliente. Não sabia que isso é por design. Sinto que o seu design ruim gera exceção nos fluxos de código normais. Graças a Deus pelo método sobrecarregado.
Pavan Manjunath
2
@MSaudi Isso está usando uma chamada assíncrona, certifique-se de entender que seu código não irá parar enquanto estiver processando os dados que estão sendo retornados. O exemplo usa msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx . Basicamente, você precisa ter uma StateObjectclasse public byte[] buffer = new byte[1024], public Socket socket;e chamar uma função chamada Receive(Socket s), que faz StateObject so = new StateObject(); so.socket = s; s.BeginReceive(so.buffer, 0, 256, 0, new AsyncCallback(ReceiveCallback), so); e na qual void ReceiveCallback(IAsyncResult ar)você chama esse código, acima.
vapcguy
2
@cagatay Embora ele ofereça uma solução, nunca vi valor em métodos assíncronos em que você precisa saber imediatamente o que está voltando depois de fazer o seu Sendantes de poder fazer qualquer outra coisa.
Vapcguy # 9/17
3
Na verdade, descobri que esse método não é infalível. Também pode causar o erro do OP: stackoverflow.com/questions/17790612/…
vapcguy
10

Solução simples para esse problema irritante comum:

Basta ir ao seu arquivo ".context.cs" (localizado em " .context.tt", localizado no arquivo "* .edmx").

Em seguida, adicione esta linha ao seu construtor:

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

Espero que isso seja útil.

ayheber
fonte
@Esi onde colocar isso? e nenhum tipo de retorno ??
Khalil Khalaf
2
@ FirstStep: Porque este é um construtor.
Nikhil Agrawal
3
Isso ajuda apenas aqueles que usam o Entity Framework que estão enfrentando o problema, não aqueles que estão socket.Send(x); byte[] buffer = new byte[1]; socket.Receive(buffer, 0, 1, 0);lendo de forma simples os bytes retornados, que era o problema do OP.
vapcguy
se usar ENTITY FRAMEWORKapenas esta solução funciona !!! só isso ! Obrigado mano :)
Rao Hammas
9

Teve o mesmo bug. Realmente funcionou caso o tráfego fosse enviado usando algum proxy (violinista no meu caso). Estrutura .NET atualizada de 4.5.2 para> = 4.6 e agora tudo funciona bem. A solicitação real foi:
new WebClient().DownloadData("URL");
A exceção foi:

SocketException: uma conexão existente foi fechada à força pelo host remoto

0x49D1
fonte
5
Esta foi uma maneira de resolver as coisas para mim. Na verdade, estava relacionado a qual versão do TLS .NET era usada por padrão. 4.5.2 e inferior usaram o TLS 1.0, enquanto 4.6 e superior são mais inteligentes em permitir 1.1 e 1.2. Isso também foi possível ao reduzir o requisito TLS no servidor para 1.0, que também corrigiu o problema.
HotN
4

Eu tenho essa exceção por causa da referência circular em entity.In entidade que se parece com

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

Adicionei [IgnoreDataMemberAttribute] à propriedade Parent. E isso resolveu o problema.

Bazaleev Nikolay
fonte
2

Se estiver executando no serviço .Net 4.5.2

Para mim, o problema foi agravado porque a chamada estava sendo executada em um serviço .Net 4.5.2. Segui a sugestão @willmaz, mas recebi um novo erro.

Ao executar o serviço com o log ativado, eu vi que o handshaking com o site de destino iniciaria ok (e enviaria o token do portador), mas na etapa seguinte para processar a chamada Pós, parece que o token de autenticação seria descartado e o site responda com Unauthorized.

Descobriu-se que as credenciais do pool de serviços não tinham direitos para alterar o TLS (?) E quando eu coloquei minha conta de administrador local no pool, tudo funcionou.

ΩmegaMan
fonte
2

Para qualquer pessoa que esteja recebendo essa exceção ao ler dados do fluxo, isso pode ajudar. Eu estava recebendo essa exceção ao ler o HttpResponseMessage em um loop como este:

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

Depois de algum tempo, descobri que o culpado era o tamanho do buffer, que era muito pequeno e não funcionava bem com minha instância fraca do Azure. O que ajudou foi alterar o código para:

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

O método CopyTo () tem um tamanho de buffer padrão 81920. O buffer maior acelerou o processo e os erros pararam imediatamente, provavelmente porque as velocidades gerais de download aumentaram. Mas por que a velocidade do download é importante para impedir esse erro?

É possível que você seja desconectado do servidor porque as velocidades de download caem abaixo do limite mínimo que o servidor está configurado para permitir. Por exemplo, caso o aplicativo do qual você está baixando o arquivo esteja hospedado no IIS, pode haver um problema com a configuração http.sys:

"Http.sys é a pilha de protocolos http que o IIS usa para executar a comunicação http com os clientes. Ele possui um timer chamado MinBytesPerSecond, responsável por interromper a conexão se a taxa de transferência cair abaixo de algum limite de kb / s. Por padrão, esse limite é definido para 240 kb / seg. "

O problema é descrito neste antigo post da equipe de desenvolvimento do TFS e diz respeito especificamente ao IIS, mas pode indicar a direção certa. Ele também menciona um bug antigo relacionado a este atributo http.sys: link

Caso você esteja usando os serviços de aplicativos do Azure e o aumento do tamanho do buffer não elimine o problema, tente aumentar sua máquina também. Você receberá mais recursos, incluindo largura de banda da conexão.

Andrej Lucansky
fonte
0

Eu tive o mesmo problema e consegui resolvê-lo eventualmente. No meu caso, a porta para a qual o cliente envia a solicitação não tinha um certificado SSL vinculado a ela. Por isso, resolvi o problema vinculando um certificado SSL à porta no lado do servidor. Feito isso, essa exceção foi embora.

iefgnoix
fonte
-1

Este erro ocorreu no meu aplicativo com o protocolo CIP sempre que não enviava ou recebia dados em menos de 10s.

Isso foi causado pelo uso do método open forward. Você pode evitar isso trabalhando com outro método ou instalando uma taxa de atualização menor que os 10s que mantêm sua conexão direta com a frente.

Belekz
fonte