Istniejące połączenie zostało przymusowo zamknięte przez zdalnego hosta

159

Pracuję z komercyjną aplikacją, która wyrzuca SocketException z komunikatem,

Istniejące połączenie zostało przymusowo zamknięte przez zdalnego hosta

Dzieje się tak w przypadku połączenia gniazdowego między klientem a serwerem. Połączenie jest żywe i dobre, a mnóstwo danych jest przesyłanych, ale potem zostaje rozłączone znikąd.

Czy ktoś to widział wcześniej? Jakie mogą być przyczyny? Mogę odgadnąć kilka przyczyn, ale czy istnieje sposób, aby dodać więcej do tego kodu, aby ustalić, jaka może być przyczyna?

Wszelkie komentarze / pomysły są mile widziane.

... Najnowszy ...

Mam trochę logowania z niektórych śledzenia .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

Na podstawie innych części logowania zauważyłem, że napis „0 # 0” oznacza, że ​​wysyłany jest pakiet o długości 0 bajtów. Ale co to naprawdę oznacza?

Występuje jedna z dwóch możliwości i nie jestem pewien, która

1) Połączenie jest zamykane, ale dane są następnie zapisywane w gnieździe, tworząc w ten sposób wyjątek powyżej. 0 # 0 oznacza po prostu, że nic nie zostało wysłane, ponieważ gniazdo było już zamknięte.

2) Połączenie jest nadal otwarte i wysyłany jest pakiet zerowych bajtów (tj. Kod zawiera błąd), a wartość 0 # 0 oznacza, że ​​próbowano wysłać pakiet zerowych bajtów.

Co o tym myślisz? Wydaje mi się, że to może być niejednoznaczne, ale może ktoś inny widział takie rzeczy?

Piotr
źródło
Tylko aktualizacja. Wygląda na to, że wireshark w tym przypadku nie przerwie tego z powodu naszej konfiguracji sieci. Ale mam nadzieję, że spróbuję tego, blogs.msdn.com/dgorti/archive/2005/09/18/471003.aspx, który śledzi za pomocą .NET, który powinien wygenerować kilka plików dziennika. Będę was informować ...
Piotr
1
comcast jest również znany z wysyłania „zerowych” pakietów sfałszowanych fałszywym identyfikatorem, aby zepsuć ruch p2p ---

Odpowiedzi:

98

Zwykle oznacza to, że strona zdalna zamknęła połączenie (zwykle wysyłając RSTpakiet TCP / IP ). Jeśli pracujesz z aplikacją innej firmy, prawdopodobne przyczyny to:

  • Wysyłasz zniekształcone dane do aplikacji (co może obejmować wysłanie żądania HTTPS do serwera HTTP)
  • Z jakiegoś powodu połączenie sieciowe między klientem a serwerem jest przerywane
  • Wywołałeś błąd w aplikacji innej firmy, który spowodował awarię
  • Aplikacja innej firmy wyczerpała zasoby systemowe

Prawdopodobnie pierwszy przypadek jest tym, co się dzieje.

Możesz odpalić Wireshark, aby dokładnie zobaczyć, co dzieje się na przewodzie, aby zawęzić problem.

Bez bardziej szczegółowych informacji jest mało prawdopodobne, aby ktokolwiek tutaj mógł naprawdę pomóc.

RarrRarrRarr
źródło
2
Wspaniały. Dzięki. Inna sprawa o Wireshark. Zbiera tak dużo danych, w jaki sposób mógłbym odfiltrować coś takiego? Jeśli wireshark coś pokaże, opublikuję to tutaj później ...
Piotr
4
Powinieneś być w stanie przefiltrować zrzut Wireshark przynajmniej według adresu IP i numeru portu. Potem prawdopodobnie najbardziej pomocne jest spojrzenie na koniec strumienia (gdzie coś poszło nie tak) i cofanie się, aż zobaczysz, gdzie coś się popsuło. W zależności od złożoności stosowanego protokołu, może to być naprawdę łatwe lub prawie niemożliwe ...
RarrRarrRarr
4
Czy istnieje źródło elementów wypunktowanych, czy też poniższa odpowiedź gracza po prostu skopiowała Twoją listę?
Zack,
7
Należy pamiętać, że „wysyłanie zniekształconych danych” może oznaczać wysłanie httpsżądania do httpserwera i prawdopodobnie na odwrót.
AXMIM,
2
W moim przypadku otrzymywałem ten wyjątek tylko podczas wywoływania interfejsu API podczas lokalnego uruchamiania aplikacji. Żadnych problemów w środowiskach dev, qa lub prod. Poprawka? Lokalnie przy użyciu protokołu http zamiast https. Uważamy, że może to być związane z systemem równoważenia obciążenia. Ale właśnie zaktualizowaliśmy nasze pliki dev, qa i prod web.config z przekształceniami dla https. Problem rozwiązany.
Kershaw
82

Użycie protokołu TLS 1.2 rozwiązało ten błąd.
Możesz wymusić korzystanie z TLS 1.2 w swojej aplikacji (upewnij się, że wykonałeś go przed wywołaniem usługi):

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 

Inne rozwiązanie:
Włącz silną kryptografię na komputerze lokalnym lub serwerze, aby korzystać z protokołu TLS1.2, ponieważ domyślnie jest on wyłączony, więc używany jest tylko protokół TLS1.0.
Aby włączyć silną kryptografię, wykonaj te polecenia w PowerShell z uprawnieniami administratora:

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 

Aby zmiany zaczęły obowiązywać, musisz ponownie uruchomić komputer.

willmaz
źródło
1
Możesz dodać wiele wartości razem, aby obsługiwać wiele protokołów. Aby obsługiwać wszystko, od SSL3 do TLS1.2, ustaw SecurityProtocol = (SecurityProtocolType) 4080.
Abacus
29

To nie jest błąd w Twoim kodzie. Pochodzi z implementacji Socket .Net. Jeśli używasz przeciążonej implementacji EndReceive, jak poniżej, nie otrzymasz tego wyjątku.

    SocketError errorCode;
    int nBytesRec = socket.EndReceive(ar, out errorCode);
    if (errorCode != SocketError.Success)
    {
        nBytesRec = 0;
    }
cagatay
źródło
1
Pochodzi z systemu operacyjnego, a ostatecznie od partnera. Wymagane jest dalsze wyjaśnienie zarzutu, że jest to błąd oprogramowania.
Markiz Lorne
5
+1. W moim programie C # waliłem się w głowę, dlaczego EndReceiverzucam wyjątek, gdy następuje wdzięczne zakończenie klienta. Nie wiedziałem, że jest to zgodne z projektem. Uważam, że rzucanie wyjątków w normalnych przepływach kodu jest złym rozwiązaniem. Dzięki Bogu za przeciążoną metodę.
Pavan Manjunath
2
@MSaudi To używa wywołania asynchronicznego, upewnij się, że rozumiesz, że Twój kod nie zatrzyma się podczas przetwarzania zwracanych danych. Przykład używa msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx . Zasadniczo musisz mieć StateObjectklasę z public byte[] buffer = new byte[1024], public Socket socket;wywołaną funkcją i wywołać ją Receive(Socket s), która to robi StateObject so = new StateObject(); so.socket = s; s.BeginReceive(so.buffer, 0, 256, 0, new AsyncCallback(ReceiveCallback), so); i void ReceiveCallback(IAsyncResult ar)wywołujesz ten kod powyżej.
vapcguy
2
@cagatay Chociaż oferuje rozwiązanie, nigdy nie widziałem wartości w metodach asynchronicznych, w których musisz od razu wiedzieć, co wraca po wykonaniu, Sendzanim będziesz mógł zrobić cokolwiek innego.
vapcguy
3
Właściwie odkryłem, że ta metoda nie jest niezawodna. Może również powodować błąd OP: stackoverflow.com/questions/17790612/ ...
vapcguy
10

Proste rozwiązanie tego powszechnego irytującego problemu:

Po prostu przejdź do pliku.context.cs” (znajdującego się pod „ .context.tt”, który znajduje się pod Twoim plikiem „* .edmx”).

Następnie dodaj tę linię do swojego konstruktora:

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

mam nadzieję, że to jest pomocne.

ayheber
źródło
@Esi gdzie to umieścić? i nie ma typu powrotu?
Khalil Khalaf
2
@FirstStep: Bo to jest konstruktor.
Nikhil Agrawal
3
Pomaga to tylko tym, którzy używają Entity Framework, u których występuje problem, a nie tym, którzy wykonują proste socket.Send(x); byte[] buffer = new byte[1]; socket.Receive(buffer, 0, 1, 0);odczytywanie zwróconych bajtów, co było problemem OP.
vapcguy
czy używanie ENTITY FRAMEWORKtylko tego rozwiązania działa !!! tylko to ! dzięki bracie :)
Rao Hammas
9

Miał ten sam błąd. Faktycznie zadziałało w przypadku, gdy ruch był przesyłany za pomocą jakiegoś proxy (skrzypek w moim przypadku). Zaktualizowany .NET framework z 4.5.2 do> = 4.6 i teraz wszystko działa dobrze. Rzeczywista prośba była następująca:
new WebClient().DownloadData("URL");
Wyjątkiem był:

SocketException: istniejące połączenie zostało przymusowo zamknięte przez zdalnego hosta

0x49D1
źródło
5
To był jedyny sposób na rozwiązanie moich problemów. W rzeczywistości było to związane z używaną domyślnie wersją TLS .NET. 4.5.2 i niższe używane TLS 1.0, podczas gdy 4.6 i nowsze są mądrzejsze, jeśli chodzi o zezwolenie na 1.1 i 1.2. Można to również udowodnić, obniżając wymaganie TLS na serwerze do 1.0, co również rozwiązało problem.
HotN
4

Mam ten wyjątek z powodu cyklicznego odniesienia w entity.In entity, który wygląda jak

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

Dodałem [IgnoreDataMemberAttribute] do właściwości Parent. I to rozwiązało problem.

Bazaleev Nikolay
źródło
2

Jeśli działa w usłudze A .Net 4.5.2

Dla mnie problem został spotęgowany, ponieważ połączenie było uruchomione w usłudze .Net 4.5.2. Postępowałem zgodnie z sugestią @willmaz, ale pojawił się nowy błąd.

Podczas uruchamiania usługi z włączonym logowaniem widziałem, że uzgadnianie z witryną docelową zainicjuje prawidłowe (i wyśle ​​token okaziciela), ale w następnym kroku w celu przetworzenia wywołania Post wydaje się, że porzuci token uwierzytelniania, a witryna odpowiedz z Unauthorized.

Okazało się, że dane uwierzytelniające puli usług nie mają uprawnień do zmiany TLS (?) I kiedy wstawiłem do puli moje konto administratora lokalnego, wszystko działało.

ΩmegaMan
źródło
2

Może to pomóc każdemu, kto otrzymuje ten wyjątek podczas odczytywania danych ze strumienia. Otrzymałem ten wyjątek podczas czytania HttpResponseMessage w pętli takiej jak ta:

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

Po pewnym czasie odkryłem, że winowajcą był rozmiar bufora, który był zbyt mały i nie radził sobie dobrze z moją słabą instancją Azure. Pomogła zmiana kodu na:

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

Metoda CopyTo () ma domyślny rozmiar bufora 81920. Większy bufor przyspieszył proces, a błędy natychmiast się zatrzymały, najprawdopodobniej z powodu zwiększenia ogólnej prędkości pobierania. Ale dlaczego prędkość pobierania miałaby znaczenie w zapobieganiu temu błędowi?

Możliwe, że zostaniesz rozłączony z serwerem, ponieważ prędkość pobierania spadnie poniżej minimalnego progu, na jaki serwer jest skonfigurowany. Na przykład, jeśli aplikacja, z której pobierasz plik, jest hostowana w IIS, może to być problem z konfiguracją http.sys:

„Http.sys jest stosem protokołów HTTP używanym przez IIS do komunikacji http z klientami. Posiada licznik czasu o nazwie MinBytesPerSecond, który jest odpowiedzialny za przerywanie połączenia, jeśli jego szybkość transmisji spadnie poniżej pewnego progu kb / s. Domyślnie ten próg to ustawione na 240 kb / sek. ”

Problem został opisany w tym starym poście na blogu zespołu programistów TFS i dotyczy w szczególności usług IIS, ale może wskazać właściwy kierunek. Wspomina również o starym błędzie związanym z tym atrybutem http.sys: link

Jeśli korzystasz z usług aplikacji platformy Azure i zwiększenie rozmiaru buforu nie eliminuje problemu, spróbuj również skalować swój komputer. Otrzymasz więcej zasobów, w tym przepustowość połączenia.

Andrej Lucansky
źródło
0

Miałem ten sam problem i ostatecznie udało mi się go rozwiązać. W moim przypadku port, do którego klient wysyła żądanie, nie ma powiązanego certyfikatu SSL. Rozwiązałem więc problem, wiążąc certyfikat SSL z portem po stronie serwera. Kiedy to zostało zrobione, ten wyjątek zniknął.

iefgnoix
źródło
-1

Ten błąd pojawił się w mojej aplikacji z protokołem CIP, gdy nie wysłałem lub nie otrzymałem danych w czasie krótszym niż 10 sekund.

Było to spowodowane użyciem metody forward open. Możesz tego uniknąć, pracując z inną metodą lub instalując częstotliwość aktualizacji mniejszą niż 10, które utrzymują połączenie typu forward-open.

Belekz
źródło