Невозможно прочитать данные из транспортного соединения: существующее соединение было принудительно закрыто удаленным хостом


106

У меня есть серверное приложение, и иногда, когда клиент пытается подключиться, я получаю следующую ошибку:

введите описание изображения здесь

ПРИМЕЧАНИЕ. «Не удалось получить поток от клиента или не удалось войти в систему» ​​- это текст, добавленный мной в инструкции catch.

и строка, на которой он останавливается (sThread: строка 96):

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

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

Что может быть причиной этой проблемы? Обратите внимание, что это происходит не все время

Ответы:


64

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

На английском языке: соединение с машиной (удаленный хост / сервер / ПК, на котором работает служба) было выполнено, но поскольку служба была недоступна на этой машине, машина не знала, что делать с запросом.

Если подключение к машине было недоступно, вы бы увидели другую ошибку. Я забыл, что это такое, но это похоже на «Служба недоступна» или «Недоступна».

Изменить - добавлено

Возможно, это вызвано тем, что брандмауэр блокирует порт, но, учитывая, что вы говорите, что это периодически («иногда, когда клиент пытается подключиться»), это очень маловероятно. Я не включил это изначально, потому что мысленно исключил это, прежде чем ответить.


1
Дело в том, что когда я запускаю сервер, к моему серверу подключается около 50 клиентов. Я реализовал своего рода сигнал ожидания при приеме клиента ... что-то вроде while (Program.waitToFinishLoginAtClient == true && ajutor <30) {Thread.Sleep (300); аютор ++; } client = this.tcpListener.AcceptTcpClient (); Program.waitToFinishLoginAtClient = true; ........... и Program.waitToFinishAtClient изменяется в потоке, содержащем клиента
Alex

могло ли это "ожидание" быть проблемой?
Alex

1
я должен просто позволить этому быть? Нет, подождите ?
Alex

1
Думаю, проблема в ожидании. Я недостаточно знаю ваш код, чтобы быть уверенным, но это звучит вполне вероятно. Просто любопытно, создали ли вы свой собственный сервис «сложным путем», или используете ли вы для этого WCF или даже Remoting ...
Дэвид

Основываясь на небольшом количестве кода, мне кажется, что проблемы «ожидания» можно было бы избежать, если бы она находилась внутри отдельного потока для каждого соединения. На всякий случай, если эта догадка верна
Дэвид

187

Я получил эту ошибку при вызове веб-сервиса. Проблема также была связана с безопасностью транспортного уровня. Я мог бы вызвать веб-службу через проект веб-сайта, но при повторном использовании того же кода в тестовом проекте я бы получил WebException, содержащий это сообщение. Добавление следующей строки перед вызовом решило проблему:

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

редактировать

System.Net.ServicePointManager.SecurityProtocol - это свойство выбирает версию протокола Secure Sockets Layer (SSL) или Transport Layer Security (TLS), которая будет использоваться для новых подключений, использующих только схему Secure Hypertext Transfer Protocol (HTTPS); существующие подключения не изменяются.

Я считаю, что SecurityProtocolконфигурация важна во время рукопожатия TLS при выборе версии протокола.

Рукопожатие TLS - этот протокол используется для обмена всей информацией, необходимой обеим сторонам для обмена фактическими данными приложения с помощью TLS.

ClientHello - клиент отправляет сообщение ClientHello с указанием самой высокой версии протокола TLS, которую он поддерживает ...

ServerHello - сервер отвечает сообщением ServerHello, содержащим выбранную версию протокола ... Выбранная версия протокола должна быть самой высокой из поддерживаемых как клиентом, так и сервером. Например, если клиент поддерживает TLS версии 1.1, а сервер поддерживает версию 1.2, следует выбрать версию 1.1; версию 1.2 выбирать не следует.


8
это спасло меня! Спасибо чувак. в моем отладчике я пытаюсь вызвать службу https во время тестирования, и у меня возникла проблема с OP.
Блэр Холмс

6
Знаем ли мы больше о том, как / почему это работает? Я боролся с вызовом PostAsync, и это, похоже, тоже исправляет мою ошибку. Рад, что это сработало, но я также хотел бы знать, почему.
Кевин Мэтлок

1
@HansVonn Спасибо за это! Сэкономил мне массу времени - относительно того, почему это работает. Это просто ограничение версии TLS, которую вы используете при подключении.
confusedandamused

1
Не могу поверить, что это снова меня достало! Спасибо
Sergio A.

2
СПАСИБО! Это сводило меня с ума.
mknopf

34

В моем конкретном случае для службы приложений Azure минимальная версия TLS была изменена на 1.2.

Я не знаю, будет ли это по умолчанию с этого момента, но вернув его к 1.0, все заработало.

Вы можете получить доступ к настройке в «Настройках SSL».


7
О боже, БОЛЬШОЕ СПАСИБО! Я застрял на этом так долго, и я проверил настройки SSL в веб-приложении, и минимальное значение было установлено на 1,2 вместо 1,0. Когда я вернул его к 1.0 и перезапустил веб-приложение, все заработало! Спасибо вам большое!
Мейсон

1
Большое спасибо, @ hugo-hilário, у меня тоже потрясающе сработало! Как тебе удалось найти такое хитрое решение! : D
hosjay

@hosjay, для меня это тоже был ад :)
Hugo Hilário

3
Спас мой дневной товарищ!
Нитеш

У меня была эта проблема для моей функции Azure v2
Питер Хемерик,

17

Не уверен, какое из исправлений в этих сообщениях в блоге помогло, но один из них решил эту проблему для меня ...

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

Уловка, которая мне помогла, заключалась в том, чтобы отказаться от использования WebRequest и вместо этого использовать HttpWebRequest. HttpWebRequest позволяет мне играть с 3 важными настройками:

и

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

  • ШАГ 1. Отключите KeepAlive.
  • ШАГ 2: Установите для ProtocolVersion значение Version10
  • ШАГ 3: Ограничение количества точек обслуживания

1
Этот ответ решил для меня ту же проблему. Я отключил "Keep Alive" в разделе Http Response Headers в IIS7
drzounds

Я должен добавить, что мне также пришлось добавить этот код в Reference.cs для веб-службы, у которой было такое поведение. защищенное переопределение System.Net.WebRequest GetWebRequest (Uri uri) {System.Net.HttpWebRequest webRequest = (System.Net.HttpWebRequest) base.GetWebRequest (uri); webRequest.KeepAlive = false; return webRequest; }
drzounds

11

Вызовы HTTPS-сервисов с одного из наших серверов также вызывали исключение « Невозможно прочитать данные из транспортного соединения: существующее соединение было принудительно закрыто ». Однако служба HTTP работала нормально. Использовал Wireshark, чтобы убедиться, что это был сбой установления связи TLS. Оказалось, что необходимо обновить набор шифров на сервере.


Вот что со мной происходило. Был отправлен сертификат с истекшим сроком действия на соединение SSL. А обновил сертификат и заработал.
Гильерме де Хесус Сантос,

8

Согласно ответам "Ганса Вонна".

Добавление следующей строки перед вызовом решило проблему:

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

После добавления протокола безопасности и нормальной работы, но я должен добавлять его перед каждым вызовом API, который не работает. Я просто обновляю версию .NET Framework не ниже 4.6 и работаю так, как ожидалось, не требует добавления перед каждым вызовом API.


1
Большое спасибо. вы сделали мой день. Для некоторых это может быть полезно, если я упомяну, что до этого я также тестировал отключение брандмауэра и добавление ServicePointManager.ServerCertificateValidationCallback, но не работал.
Текин

5

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

Я клонировал виртуальную машину и запустил ее в другой сети с новым IP-адресом, но не изменил привязки в IIS. Fiddler показывал мне «Невозможно прочитать данные из транспортного соединения: существующее соединение было принудительно закрыто удаленным хостом», а IE сообщал мне: «Включите TLS 1.0, TLS 1.1 и TLS 1.2 в дополнительных настройках». Изменение привязки к новому IP-адресу решило эту проблему.


2

По какой-то причине пропало соединение с сервером. Возможно, сервер явно закрыл соединение, или ошибка на сервере привела к его неожиданному закрытию. Или что-то между клиентом и сервером (коммутатор или маршрутизатор) разорвало соединение.

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

На клиенте вы должны написать свой код, чтобы учесть возможность отказа сервера в любой момент. Так оно и есть: сетевые соединения по своей сути ненадежны.


2

Это решило мою проблему. Я добавил эту строку перед отправкой запроса:

System.Net.ServicePointManager.Expect100Continue = false;

Похоже, что на пути к серверу был прокси, который не поддерживал поведение 100-continue.


1

Я сталкивался с этой проблемой в прошлом. Я использую PostgreSQL, и когда я запускаю свою программу, иногда она подключается, а иногда выдает такую ​​ошибку.

Когда я экспериментирую со своим кодом, я помещаю свой код подключения в самую первую строку под общедоступной формой. Вот пример:

ПЕРЕД:

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

СЕЙЧАС:

    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!

        }

Я думаю, что программа должна сначала прочитать соединение, прежде чем что-то делать, не знаю, поправьте меня, если я ошибаюсь. Но согласно моим исследованиям, это не проблема кода - на самом деле это была проблема самой машины.

Удачного кодирования!


1
System.Net.ServicePointManager.Expect100Continue = false;

Эта проблема иногда возникает из-за того, что прокси-сервер реализован на веб-сервере. Чтобы обойти прокси-сервер, поместив эту строку перед вызовом службы отправки.


0

У меня было запущено стороннее приложение (Fiddler), чтобы попытаться увидеть отправленные запросы. Закрытие этого приложения исправило это для меня


0

У нас была очень похожая проблема, когда веб-сайт клиента пытался подключиться к нашей службе веб-API и получал то же сообщение. Это начало происходить совершенно неожиданно, когда на сервере, где работал IIS, не было изменений кода или обновлений Windows.

В нашем случае выяснилось, что вызывающий веб-сайт использует версию .Net, которая поддерживает только TLS 1.0, и по какой-то причине сервер, на котором работал наш IIS, остановился, похоже, перестал принимать вызовы TLS 1.0. Чтобы диагностировать это, нам пришлось явно включить TLS через реестр на сервере IIS, а затем перезапустить этот сервер. Это ключи реестра:

[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

В моем ответе на другой вопрос есть этот сценарий PowerShell, который мы использовали для добавления записей:

ПРИМЕЧАНИЕ. Включение старых протоколов безопасности - не очень хорошая идея, правильным ответом в нашем случае было заставить веб-сайт клиента обновить свой код для использования TLS 1.2, но записи реестра выше могут помочь в первую очередь диагностировать проблему.


0

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

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

Исправление заключалось в том, чтобы просто удалить регистрацию службы второй области

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

0

Если у вас есть сертификат https в домене, убедитесь, что у вас есть привязка https к имени домена в IIS. В IIS -> Выберите свой домен -> Нажмите "Привязки". Откроется окно "Привязки к сайту". Добавьте привязку для https.


0

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

Рукопожатие HTTPS для [blah] (для # 136) не выполнено. System.IO.IOException Невозможно прочитать данные из транспортного соединения: существующее соединение было принудительно закрыто удаленным хостом

и

Ошибка ReadResponse (): сервер не вернул полный ответ на этот запрос. Сервер вернул 0 байт.

Проблема оказалась в том, что сертификат SSL-сервера был пропущен и не был установлен на паре серверов.


0

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


0

Другой вариант - проверить код ошибки, сгенерированный с помощью блока try-catch, и сначала перехватить WebException.

В моем случае код ошибки был «SendFailure» из-за проблемы с сертификатом на URL-адресе HTTPS, как только я нажимаю HTTP, эта проблема решается.

https://docs.microsoft.com/en-us/dotnet/api/system.net.webexceptionstatus?redirectedfrom=MSDN&view=netframework-4.8


0

Для меня это была проблема, когда в привязке IIS был IP-адрес веб-сервера. Я изменил его, чтобы использовать все неназначенные IP-адреса, и мое приложение начало работать.


0

Я столкнулся с ошибкой при запуске python clr mdx-запроса к аналитическим службам Microsoft с использованием adomd

Я решил это с помощью Ханса Вонна, и вот версия на питоне :

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

0

Для тех, кто может найти это позже, после .NET версии 4.6, я тоже столкнулся с этой проблемой.

Убедитесь, что вы проверили файл web.config на наличие следующих строк:

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

Если вы используете 4.6.x или более позднюю версию .NET на сервере, убедитесь, что вы настроили эти значения targetFramework в соответствии с версией платформы на вашем сервере. Если ваши версии меньше 4.6.x, то я бы порекомендовал вам обновить .NET и использовать более новую версию, если ваш код не зависит от более старой версии (что в этом случае вам следует подумать об обновлении).

Я изменил targetFrameworks на 4.7.2, и проблема исчезла:

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.