Существующее соединение было принудительно закрыто удаленным хостом

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 означает, что пакет с нулевыми байтами пытается быть отправлен.

Как вы думаете? Это может быть неубедительным, я думаю, но, возможно, кто-то еще видел такие вещи?

Питер
источник
Просто обновление. Кажется, что Wireshark не собирается сокращать его в этом случае из-за нашей настройки сети. Но, надеюсь, я собираюсь попробовать это, blogs.msdn.com/dgorti/archive/2005/09/18/471003.aspx, который отслеживает использование .NET, которое должно создавать некоторые файлы журналов. Я буду держать вас в курсе ...
Питер
1
Также известно, что comcast отправляет «нулевые» пакеты, подделанные поддельным идентификатором, чтобы связываться с трафиком p2p ---

Ответы:

98

Как правило, это означает, что удаленная сторона закрыла соединение (обычно путем отправки RSTпакета TCP / IP ). Если вы работаете со сторонним приложением, вероятные причины:

  • Вы отправляете искаженные данные в приложение (что может включать отправку HTTPS-запроса на HTTP-сервер)
  • Сетевая связь между клиентом и сервером по какой-то причине прерывается
  • Вы вызвали ошибку в стороннем приложении, которая вызвала его сбой
  • Стороннее приложение исчерпало системные ресурсы

Вполне вероятно, что в первом случае происходит то, что происходит.

Вы можете запустить Wireshark, чтобы точно увидеть, что происходит на проводе, чтобы сузить проблему.

Без более конкретной информации маловероятно, что кто-то здесь действительно может вам сильно помочь.

RarrRarrRarr
источник
2
Отлично. Спасибо. Другая вещь о Wireshark. Он собирает так много данных, как бы я мог отфильтровать что-то вроде этого? Если Wireshark обнаружит что-то, я мог бы опубликовать это здесь позже ...
Питер
4
Вы должны быть в состоянии фильтровать дамп Wireshark, по крайней мере, по IP-адресу и номеру порта. После этого, вероятно, наиболее полезно посмотреть на конец потока (где что-то пошло не так) и работать в обратном направлении, пока вы не сможете определить, где что-то не так. В зависимости от сложности используемого протокола, это может быть очень легко или почти невозможно ...
RarrRarrRarr
4
Есть ли источник для маркированных предметов, или ответ игрока ниже просто скопировал ваш список?
Zack
7
Обратите внимание, что «отправка неверных данных» может означать отправку httpsзапроса на httpсервер и, возможно, наоборот.
AXMIM
2
В моем случае я получал это исключение только при вызове API при локальном запуске приложения. Никаких проблем в средах dev, qa или prod. Исправление? Использование http вместо https локально. Мы думаем, что это может быть связано с балансировщиком нагрузки. Но мы только что обновили наши dev, 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 

Вам необходимо перезагрузить компьютер, чтобы эти изменения вступили в силу.

willmaz
источник
1
Вы можете добавить несколько значений вместе для поддержки нескольких протоколов. Поэтому для поддержки всего, от SSL3 до TLS1.2, установите SecurityProtocol = (SecurityProtocolType) 4080.
Абак
29

Это не ошибка в вашем коде. Это происходит от реализации Socket .Net. Если вы используете перегруженную реализацию EndReceive, как показано ниже, вы не получите это исключение.

    SocketError errorCode;
    int nBytesRec = socket.EndReceive(ar, out errorCode);
    if (errorCode != SocketError.Success)
    {
        nBytesRec = 0;
    }
Cagatay
источник
1
Это исходит от операционной системы, и в конечном итоге от сверстника. Требуется дополнительное объяснение утверждения, что это программная ошибка.
маркиз Лорн
5
+1. В моей программе на C # я ломал голову над тем, почему EndReceiveвыбрасывает исключение при изящном завершении клиента. Не знал, что это по замыслу. Я чувствую его плохой дизайн, чтобы генерировать исключения в обычных потоках кода. Слава Богу за перегруженный метод.
Паван Манджунат,
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 !
    }

надеюсь, что это полезно.

ayheber
источник
@ Еси где это поставить? а нет типа возврата ??
Халил Халаф
2
@FirstStep: Потому что это конструктор.
Нихил Агравал
3
Это помогает только тем, кто использует Entity Framework, испытывающим проблему, а не тем, кто делает простое socket.Send(x); byte[] buffer = new byte[1]; socket.Receive(buffer, 0, 1, 0);чтение возвращенных байтов, что было проблемой OP.
vapcguy
если использовать ENTITY FRAMEWORKтолько это решение работает !!! только это ! спасибо братан :)
Рао
9

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

SocketException: существующее соединение было принудительно закрыто удаленным хостом

0x49D1
источник
5
Это был один из способов решить вещи для меня. На самом деле это было связано с тем, какая версия TLS .NET используется по умолчанию. 4.5.2 и ниже использовали TLS 1.0, в то время как 4.6 и выше умнее разрешают 1.1 и 1.2. Это также было доказано путем снижения требования TLS на сервере до 1.0, что также решило проблему.
HotN
4

Я получил это исключение из-за циклической ссылки в entity.In лица, которые выглядят как

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] в свойство Parent. И это решило проблему.

Базалеев Николай
источник
2

Если работает в службе .Net 4.5.2

Для меня проблема была усугублена, потому что вызов выполнялся в службе .Net 4.5.2. Я последовал предложению @willmaz, но получил новую ошибку.

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

Оказалось, что учетные данные пула сервисов не имеют прав на изменение TLS (?), И когда я вставил свою локальную учетную запись администратора в пул, все заработало.

ΩmegaMan
источник
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: ссылка

Если вы используете службы приложений Azure и увеличение размера буфера не устраняет проблему, попробуйте также увеличить масштаб вашей машины. Вам будет выделено больше ресурсов, включая пропускную способность соединения.

Андрей Лучанский
источник
0

У меня была та же проблема, и мне удалось ее решить в конце концов. В моем случае порт, на который клиент отправляет запрос, не имеет привязки SSL-сертификата. Поэтому я исправил проблему, привязав сертификат SSL к порту на стороне сервера. Как только это было сделано, это исключение исчезло.

iefgnoix
источник
-1

Эта ошибка возникала в моем приложении с CIP-протоколом, когда я не отправлял и не получал данные менее чем за 10 секунд.

Это было вызвано использованием метода прямого открытия. Вы можете избежать этого, работая с другим методом, или установить частоту обновления менее 10 с, поддерживающую ваше прямое открытое соединение.

Belekz
источник