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


103

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

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

ПРИМІТКА: "Не вдалося отримати потік від клієнта або не вдалося ввійти" - це текст, який я додав у заяві "catch"

а лінія, на якій він зупиняється (sThread: рядок 96), є:

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

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

Що може спричинити цю проблему? Зауважте, що це не відбувається постійно

Відповіді:


63

Ця помилка означає, що цільова машина працює, але послуга, до якої ви намагаєтесь підключитися, недоступна. (Або він зупинився, вийшов з ладу або зайнятий іншим запитом.)

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

Якщо підключення до машини не було, ви побачите іншу помилку. Я забуваю, що це таке, але це так, як "Сервіс недоступний" або "Недоступний".

Редагувати - додано

Цілком можливо, що це викликано брандмауером, який блокує порт, але враховуючи, що ви кажете, що він переривчастий ("іноді, коли клієнт намагається підключитися"), це малоймовірно. Я не включав це спочатку, тому що подумки виключив це перед тим, як відповісти.


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

Чи може це проблема "чекати"?
Алекс

1
я повинен просто дозволити це бути? не чекайте?
Алекс

1
Я думаю, що проблема чекає. Я не знаю достатньо вашого коду, щоб бути впевненим, але це впевнено звучить. Цікаво, чи побудували ви власну службу "важким способом" чи ви використовуєте для цього WCF або навіть віддалений ...
David

Виходячи з маленької нитки коду, мені здається, що проблеми "чекати" можна було б уникнути, якби вона була в окремому потоці для кожного з'єднувача. На випадок, якщо ця здогадка є правильною, ось приклад багатопотокової служби TCP з багатопотоковою передачею, яка може вам допомогти: switchchonthecode.com/tutorials/…
David

180

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

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

Редагувати

System.Net.ServicePointManager.SecurityProtocol - ця властивість вибирає версію протоколу рівня захищених сокетів (SSL) або безпеки транспортного рівня (TLS) для використання для нових з'єднань, які використовують тільки протокол передачі захищеного гіпертексту (HTTPS); існуючі з'єднання не змінені.

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

Рукостискання TLS - Цей протокол використовується для обміну всією інформацією, необхідною обома сторонами для обміну фактичними даними програми TLS.

ClientHello - Клієнт надсилає повідомлення ClientHello із зазначенням найвищої версії протоколу TLS, яку він підтримує ...

ServerHello - Сервер відповідає на повідомлення ServerHello, що містить обрану версію протоколу ... Вибрана версія протоколу повинна бути найвищою, яку підтримують і клієнт, і сервер. Наприклад, якщо клієнт підтримує TLS версії 1.1, а сервер підтримує версію 1.2, слід вибрати версію 1.1; не слід вибирати версію 1.2.


8
це врятувало мене! дякую людині. у своєму відладчику я намагаюся зателефонувати на службу https під час тестування, і у мене виникли проблеми, з якими виникало ОП
Блер Холмс

6
Чи знаємо ми більше про те, як / чому це працює? Я боровся з викликом PostAsync, і це, здається, теж виправляє мою помилку. Радий, що це спрацювало, але я також хотів би знати, чому.
Кевін Матлок

1
@HansVonn Дякую за це! Заощадило мені багато часу - Що стосується того, чому це працює, це просто обмеження версії TLS, яку ви використовуєте під час підключення.
confusedandamused

1
Не можу повірити, що це мені знову! Спасибі
Серхіо А.

2
СПАСИБІ! Це ганяло мене.
mknopf

34

Мій конкретний сценарій випадку полягав у тому, що для служби додатків Azure мінімальна версія TLS була змінена на 1,2

Я не знаю, чи це зараз за замовчуванням, але повернення його до 1,0 змусило його працювати.

Ви можете отримати доступ до налаштування всередині "Налаштування SSL".


7
О, мій боже, ДЯКУЄТЕ ТАКІ МНОГО! Я довгий час затримався на цьому, і я перевірив настройки SSL веб-програми, а мінімум встановлено на 1,2, а не на 1,0. Коли я змінив його на 1,0 та перезапустив веб-додаток, він працював! Дуже дякую!
Мейсон

1
Велике спасибі, @ hugo-hilário, напрочуд він працював і для мене! Як же ти встиг знайти таке хитре рішення! : D
хосей

@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 дозволяє мені грати з трьома важливими параметрами:

і

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

  • КРОК 1: Вимкнути KeepAlive
  • КРОК 2: Встановіть ProtocolVersion на Версію10
  • КРОК 3: Обмеження кількості точок обслуговування

1
Ця відповідь - це те, що вирішило цю саму проблему для мене. Я вимкнув "Keep Alive" у розділі заголовки відповідей Http в IIS7
drzounds

Я мушу додати, що мені також довелося додати цей код до Reference.cs для веб-сервісу, який мав таку поведінку. захищений перезапис System.Net.WebRequest GetWebRequest (Uri uri) {System.Net.HttpWebRequest webRequest = (System.Net.HttpWebRequest) base.GetWebRequest (uri); webRequest.KeepAlive = false; повернути веб-запит; }
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

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

Я клонував VM і запустив його в іншій мережі з новою IP-адресою, але не змінив прив’язки в IIS. Фіддлер показав мені "Неможливо прочитати дані з транспортного з'єднання. Віддалений хост був примусово закритий, і IE сказав мені" Увімкніть TLS 1.0, TLS 1.1 та TLS 1.2 у додаткових налаштуваннях ". Зміна прив’язки до нової IP-адреси вирішила це для мене.


2

Чомусь було втрачено з’єднання з сервером. Можливо, сервер явно закрив з'єднання, або помилка на сервері спричинила його закриття несподівано. Або щось між клієнтом і сервером (комутатор або маршрутизатор) перервало з'єднання.

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

На клієнті ви повинні написати свій код, щоб врахувати можливість відмови сервера в будь-який час. Ось так і є: мережеві з'єднання по суті є ненадійними.


2

Це вирішило мою проблему. Я додав цей рядок до того, як буде зроблено запит:

System.Net.ServicePointManager.Expect100Continue = false;

Здавалося, що на шляху сервера є проксі-сервер, який не підтримує поведінку 100-ти продовження.


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 та отримувати те саме повідомлення. Це почало відбуватися зовсім не так, коли не було змін коду чи оновлень Windows на сервері, де працює IIS.

У нашому випадку виявилося, що веб-сайт, що викликає, використовує версію .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

У моїй відповіді на інше запитання тут є сценарій оболонки повноважень, який ми використовували для додавання записів:

ПРИМІТКА. Увімкнення старих протоколів безпеки - це не дуже гарна ідея, правильною відповіддю в нашому випадку було змусити веб-сайт клієнта оновити його код для використання TLS 1.2, але записи вище в реєстрі можуть допомогти діагностувати проблему в першу чергу.


0

Причиною цього в мене було те, що я мав рекурсивну залежність у свого постачальника ІД. У моєму випадку у мене було:

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 до [бла] (для № 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

У мене виникла помилка під час виконання запиту mdx python clr до аналітичних служб 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.