Існуюче з'єднання було насильно закрито віддаленим хостом


159

Я працюю з комерційним додатком, який передає SocketException з повідомленням,

Існуюче з'єднання було насильно закрито віддаленим хостом

Це відбувається при з'єднанні сокета між клієнтом і сервером. Зв'язок є живим і здоровим, і купа даних передається, але потім він відключається з нізвідки.

Хтось бачив це раніше? Які можуть бути причини? Я можу напевно припустити декілька причин, але чи є якийсь спосіб додати більше в цей код, щоб розібратися, що може бути причиною?

Будь-які коментарі / ідеї вітаються.

... Останній ...

У мене є журнал із деякого трактування .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

На основі інших частин журналу я бачив той факт, що в ньому написано, що "0 # 0" означає, що відправляється пакет довжиною 0 байт. Але що це насправді означає?

Одна з двох можливостей є, і я не впевнений, який,

1) З'єднання закривається, але дані записуються в сокет, створюючи виняток вище. 0 # 0 просто означає, що нічого не було надіслано, оскільки сокет вже закритий.

2) З'єднання все ще відкрите, і пакет нульових байтів надсилається (тобто код має помилку), а 0 # 0 означає, що пакет нульових байтів намагається надіслати.

Що ти вважаєш? Можливо, це може бути непереконливим, але, можливо, хтось ще бачив подібне?


Просто оновлення. Здається, що провідний шарк не збирається скорочувати це в цьому випадку через налаштування нашої мережі. Але я сподіваюся, що я спробую це спробувати blogs.msdn.com/dgorti/archive/2005/09/18/471003.aspx, який простежує за допомогою .NET, який повинен створювати деякі файли журналів. Я буду тримати вас у курсі ...
Peter

1
Comcast також відомий, що надсилає "нульові" пакети, підроблені фальшивим ідентифікатором, щоб возитися з трафіком p2p ---

Відповіді:


98

Це, як правило, означає, що віддалена сторона закрила з'єднання (як правило, надсилаючи TCP / IP- RSTпакет). Якщо ви працюєте зі стороннім додатком, ймовірні причини:

  • Ви надсилаєте неправильно сформовані дані до програми (що може включати надсилання HTTPS-запиту на HTTP-сервер)
  • Мережевий зв’язок між клієнтом і сервером чомусь відпадає
  • Ви викликали помилку в сторонній програмі, яка спричинила її збій
  • Стороннє додаток вичерпало системні ресурси

Ймовірно, що перший випадок - це те, що відбувається.

Ви можете запустити Wireshark, щоб точно побачити, що відбувається на дроті, щоб звузити проблему.

Без конкретнішої інформації навряд чи хтось тут може вам дуже допомогти.


2
Чудово. Дякую. Інша річ про дротяний шальк. Він збирає стільки даних, як я міг би відфільтрувати щось подібне? Якщо wireshark з'явиться щось, я можу опублікувати його тут пізніше ...
peter

4
Ви повинні мати можливість фільтрувати дамп Wireshark як мінімум за IP-адресою та номером порту. Після цього, мабуть, найкорисніше буде подивитися в кінці потоку (де щось пішло не так) і працювати назад, поки ви не зможете помітити, де все спочатку зіпсується. Залежно від складності залученого протоколу, це може бути дуже просто майже неможливо ...
RarrRarrRarr

4
Чи є джерело для позначених предметів, чи відповідь гравця нижче просто скопіювала ваш список?
Зак

7
Зауважте, що "надсилання неправильно сформованих даних" може означати надсилання httpsзапиту на httpсервер і, можливо, навпаки.
AXMIM

2
У моєму випадку я отримував цей виняток лише під час виклику api під час запуску програми локально. Немає проблем у середовищах dev, qa або prod. Виправлення? Використання http замість https локально. Ми думаємо, що це може бути пов'язано з балансиром навантаження. Але ми щойно оновили розробники, qa та prod web.configs з перетвореннями для https. Проблема вирішена.
Кершов

82

Використання TLS 1.2 вирішило цю помилку.
Ви можете змусити свою програму, використовуючи TLS 1.2 за допомогою цього (обов'язково виконайте її перед тим, як зателефонувати в службу):

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 

Інше рішення:
Увімкніть сильну криптографію на вашій локальній машині або сервері, щоб використовувати TLS1.2, оскільки за замовчуванням вона відключена, тому використовується лише TLS1.0.
Щоб увімкнути потужну криптографію, виконайте ці команди в PowerShell з правами адміністратора:

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 

Щоб зміни набули чинності, вам потрібно перезавантажити комп’ютер.


1
Ви можете додати кілька значень разом для підтримки декількох протоколів. Отже, щоб підтримувати все від SSL3 до TLS1.2, встановіть SecurityProtocol = (SecurityProtocolType) 4080.
Абак

29

Це не помилка у вашому коді. Це відбувається від реалізації Sonet .Net. Якщо ви використовуєте перевантажену реалізацію EndReceive, як показано нижче, виняток не отримає.

    SocketError errorCode;
    int nBytesRec = socket.EndReceive(ar, out errorCode);
    if (errorCode != SocketError.Success)
    {
        nBytesRec = 0;
    }

1
Це відбувається від операційної системи і, зрештою, від однорангової. Потрібно додаткове пояснення твердження, що це програмна помилка.
Маркіз Лорн

5
+1. У своїй програмі C # я стукав головою про те, чому EndReceiveкидають виняток, коли відбувається витончене припинення клієнта. Не знав, що це по дизайну. Я відчуваю його поганий дизайн, щоб кинути виняток у нормальних потоках коду. Слава Богу за перевантажений метод.
Pavan Manjunath

2
@MSaudi Для цього використовується асинхронний дзвінок, будьте впевнені, що ви розумієте, що ваш код не зупиниться під час обробки даних, що повертаються. Приклад використовує msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx . В основному ви повинні мати StateObjectклас з public byte[] buffer = new byte[1024], public Socket socket;і викликати функцію Receive(Socket s), яку називають , яка робить, StateObject so = new StateObject(); so.socket = s; s.BeginReceive(so.buffer, 0, 256, 0, new AsyncCallback(ReceiveCallback), so); і void ReceiveCallback(IAsyncResult ar)ви називаєте цей код вище.
vapcguy

2
@cagatay Хоча він пропонує рішення, я ніколи не бачив значення в асинхронних методах, коли вам потрібно знати відразу, що повертається після того, як ви зробите своє, Sendперш ніж ви зможете зробити щось інше.
vapcguy

3
Власне, я виявив, що цей спосіб не є надійним. Це також може привести до OP помилково: stackoverflow.com/questions/17790612 / ...
vapcguy

10

Просте рішення цього поширеного дратівливого питання:

Просто перейдіть у файл " .context.cs" (розташований під " .context.tt", який знаходиться під вашим файлом "* .edmx").

Потім додайте цей рядок до свого конструктора:

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

сподіваюся, що це корисно.


@Esi куди це поставити? і немає типу повернення ??
Халил Халаф

2
@FirstStep: Тому що це конструктор.
Nikhil Agrawal

3
Це допомагає лише тим, хто використовує Entity Framework, у якого виникають проблеми, а не тим, хто робить просто socket.Send(x); byte[] buffer = new byte[1]; socket.Receive(buffer, 0, 1, 0);прочитання повернених байтів, що було проблемою ОП.
vapcguy

якщо використовувати ENTITY FRAMEWORKтільки це рішення працює !!! тільки в цьому ! дякую
брато

9

Була така ж помилка. Насправді працював у випадку, якщо трафік був відправлений за допомогою якогось проксі (fiddler у моєму випадку). Оновлено .NET Framework від 4.5.2 до> = 4.6 і тепер усе працює добре. Фактичним запитом було:
new WebClient().DownloadData("URL");
Виняток:

SocketException: віддалений хост був примусово закритий існуючим з'єднанням


5
Це був один із способів вирішити речі для мене. Насправді це стосувалося, яку версію TLS .NET використовували за замовчуванням. 4.5.2 і новіші використовувані TLS 1.0, тоді як 4.6 і вище розумніші щодо дозволу 1.1 і 1.2. Це було також доказів, скинувши вимогу TLS на сервері до 1,0, що також вирішило проблему.
HotN

4

У мене є такий виняток через кругові посилання на сутність. У сутності, які так виглядають

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

Я додав [IgnoreDataMemberAttribute] до властивості батьків. І це вирішило проблему.


2

Якщо працює у службі .Net 4.5.2

Для мене проблема ускладнилася тим, що виклик виконувався в службі .Net 4.5.2. Я дотримувався пропозиції @willmaz, але отримав нову помилку.

Запускаючи службу з увімкненим журналом, я переглядав, що рукостискання з цільовим сайтом може ініціювати нормально (і надіслати маркер носія), але на наступному кроці для обробки Поштового дзвінка, здавалося б, випаде маркер автентичності, і сайт буде відповісти с Unauthorized.

Виявилося, що облікові дані пулу послуг не мали права змінювати TLS (?), І коли я вводив свій пул свого локального облікового запису адміністратора, це все спрацювало.


2

Для всіх, хто отримує цей виняток під час читання даних із потоку, це може допомогти. Я отримував цей виняток, читаючи HttpResponseMessage у циклі, як це:

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

Через деякий час я з'ясував, що винуватим був розмір буфера, який був занадто малим і не грав добре з моїм слабким екземпляром Azure. Що допомогло було змінити код на:

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

Метод CopyTo () має розмір буфера за замовчуванням 81920. Більший буфер прискорив процес і помилки зупинилися негайно, швидше за все, тому що загальна швидкість завантаження зросла. Але навіщо завантажувати значення швидкості, запобігаючи цій помилці?

Можливо, ви відключитесь від сервера, оскільки швидкість завантаження опускається нижче мінімальної межі, яку сервер налаштований дозволити. Наприклад, якщо програма, з якої ви завантажуєте файл, розміщена на IIS, це може бути проблемою з конфігурацією http.sys:

"Http.sys - стек протоколів http, який IIS використовує для спілкування http з клієнтами. У ньому є таймер під назвою MinBytesPerSecond, який відповідає за знищення з'єднання, якщо його швидкість передачі опускається нижче деякого порогового значення в кб / с. За замовчуванням цей поріг є встановлено на 240 кбіт / сек. "

Проблема описана у цій старій службі розробки від блогу розробників TFS і стосується IIS, але може вказати на правильне русло. Він також згадує стару помилку, пов’язану з цим атрибутом http.sys: link

Якщо ви користуєтеся послугами додатків Azure та збільшення розміру буфера не усуває проблему, спробуйте також масштабувати свою машину. Вам буде виділено більше ресурсів, включаючи пропускну здатність з'єднання.


0

У мене було те саме питання і вдалося його врешті вирішити. У моєму випадку порт, на який клієнт надсилає запит, не мав прив'язку до нього SSL-серта. Тому я вирішив проблему, прив’язавши SSL-серт до порту на стороні сервера. Як тільки це було зроблено, цей виняток пішов з життя.


-1

Ця помилка трапилась у моїй програмі із протоколом CIP щоразу, коли я не надсилав та не отримував дані менше ніж за 10 секунд.

Це було спричинено використанням методу відкритого вперед. Ви можете уникнути цього, працюючи з іншим методом або встановити швидкість оновлення менше 10-х, яка підтримує ваше прямо-відкрите з'єднання.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.