java.net.SocketException: скидання з’єднання


128

Я отримую наступну помилку при спробі прочитати з сокета. Я займаюся readInt()цим InputStream, і я отримую цю помилку. Переглядаючи документацію, це говорить про те, що клієнтська частина з'єднання закрила з'єднання. У цьому сценарії я - ​​сервер.

У мене є доступ до файлів журналу клієнта, і він не закриває з'єднання, і фактично його файли журналів підказують, що я закриваю з'єднання. Так хтось має уявлення, чому це відбувається? На що ще слід перевірити? Це виникає, коли є місцеві ресурси, які, можливо, досягають порогів?


Я зауважу, що у мене є такий рядок:

socket.setSoTimeout(10000);

безпосередньо перед readInt(). Для цього є причина (довга історія), але просто цікаво, чи існують обставини, за яких це може призвести до вказаної помилки? У мене працює сервер у моєму IDE, і мені трапилось, що його IDE застряг на точці розриву, і тоді я помітив, що такі самі помилки починають з’являтися у моїх власних журналах у моєму IDE.

У будь-якому випадку, лише згадуючи про це, сподіваюся, це не червона оселедець. :-(


У вас є сліди стека з обох сторін? Чи можете ви трохи детальніше описати архітектуру мережі? (Через дикий Інтернет? На одній машині? Десь посередині?) Чи це відбувається постійно? Або з перервами?
Стю Томпсон

Відповіді:


116

Існує кілька можливих причин.

  1. Інший кінець навмисно скинув з'єднання таким чином, що я тут не буду документувати. Рідко і, як правило, некоректно, для цього застосовується програмне забезпечення, але це невідомо для комерційного програмного забезпечення.

  2. Частіше це спричинено записом на з'єднання, яке інший кінець вже нормально закрився. Іншими словами, помилка протоколу програми.

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

  4. У Windows "програмне забезпечення, яке спричиняє переривання з'єднання", не є тим самим, як "скидання з’єднання", викликане мережевими проблемами, що надсилаються з вашого кінця. Про це є стаття бази знань Майкрософт.


@MattLyons Дякую Є набагато кращі статті MSDN, ніж це. Чесно кажучи, мені важко повірити. З'єднання навіть не буде існувати, поки не будуть встановлені правильні вихідні та цільові IP-адреси. Статті MSDN, які я бачив, стосуються постійних мережевих помилок, що вичерпують час з'єднання.
Маркіз Лорн

48

Скидання з'єднання просто означає, що отримано TCP RST. Це відбувається, коли ваш одноліток отримує дані, які він не може обробити, і для цього можуть бути різні причини.

Найпростіше, коли ви закриваєте сокет, а потім записуєте більше даних у вихідний потік. Закривши розетку, ви сказали своєму одноліткові, що ви закінчили розмову, і він може забути про ваш зв’язок. Якщо в будь-якому випадку ви надсилаєте більше даних у цьому потоці, аналог відхиляє їх за допомогою RST, щоб повідомити, що він не слухає.

В інших випадках брандмауер, що втручається, або навіть віддалений хост можуть "забути" про ваше TCP-з'єднання. Це може статися, якщо ви не надсилаєте будь-які дані протягом тривалого часу (2 години - це звичайний тайм-аут) або через те, що одноранговий перезавантажився і втратив інформацію про активні з'єднання. Надсилання даних по одному з цих неіснуючих з'єднань також спричинить RST.


Оновлення у відповідь на додаткову інформацію:

Придивіться уважно до вашої роботи з SocketTimeoutException. Цей виняток підвищується, якщо налаштований час очікування перевищено при блокуванні під час роботи сокета. Стан сокета сам по собі не змінюється, коли цей виняток скинуто, але якщо обробник винятків закриє сокет, а потім спробує записати в нього, ви перебуваєте в режимі скидання з'єднання. setSoTimeout()покликаний дати вам чистий спосіб вийти з read()операції, яка в іншому випадку може блокуватись назавжди, не роблячи брудних речей, як-от закриття сокета з іншої нитки.


Неправильно в кількох аспектах. Збір сміття та випуск процесу викликають належне закриття, а не скидання, але закриття, яке супроводжується записом однолітків, може викликати скидання, а не EOS. SocketTimeoutExceptions збільшується лише в тому випадку, якщо читач встановив час очікування читання.
Маркіз Лорн

І це не завжди означає, що було отримано RST. Це також може означати, що один був породжений цією стороною.
Маркіз Лорнський

17

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


9

Мені соромно сказати це, але коли у мене була ця проблема, я просто помилився тим, що я закривав з'єднання, перш ніж прочитати всі дані. У випадках, коли повертаються невеликі рядки, це спрацьовувало, але, ймовірно, це було пов'язано з усією відповіддю, перш ніж я закрив її.

У випадках, коли повертається більша кількість тексту, виняток було викинуто, оскільки більше, ніж буфер повертався.

Ви можете перевірити наявність цього нагляду. Пам’ятайте, що відкриття URL-адреси схоже на файл, не забудьте закрити його (відпустіть з'єднання), коли він буде повністю прочитаний


9

Вам слід дуже уважно оглянути повний слід,

У мене є серверний додаток і виправив java.net.SocketException: Connection resetсправу.

У моєму випадку це трапляється під час зчитування з Socketоб’єкта clientSocket, який закрив своє з'єднання з якихось причин. (Загублена мережа, збиток брандмауера або програми або передбачається закриття)

Насправді я відновив зв’язок, коли отримав помилку під час читання цього об’єкта Socket.

Socket clientSocket = ServerSocket.accept();
is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
int readed = is.read(); // WHERE ERROR STARTS !!!

Цікавим є те, що for my JAVA Socketякщо клієнт підключається до мого ServerSocketі закриває його з'єднання, не надсилаючи нічого is.read()дзвінків, рекурсивно. Здається, через те, що ви знаходитесь у нескінченному циклі для читання з цього сокета, ви намагаєтесь прочитати із закритого з'єднання. Якщо ви використовуєте щось подібне нижче для роботи з читанням;

while(true)
{
  Receive();
}

Тоді ви отримуєте stackTrace щось подібне нижче і далі

java.net.SocketException: Socket is closed
    at java.net.ServerSocket.accept(ServerSocket.java:494)

Що я зробив, це просто закрити ServerSocket і відновити зв’язок і чекати подальших вхідних клієнтських з'єднань

String Receive() throws Exception
{
try {                   
            int readed = is.read();
           ....
}catch(Exception e)
{
        tryReConnect();
        logit(); //etc
}


//...
}

Це відновлює моє з'єднання для невідомих втрат клієнтського сокета

private void tryReConnect()
        {
            try
            {
                ServerSocket.close();
                //empty my old lost connection and let it get by garbage col. immediately 
                clientSocket=null;
                System.gc();
                //Wait a new client Socket connection and address this to my local variable
                clientSocket= ServerSocket.accept(); // Waiting for another Connection
                System.out.println("Connection established...");
            }catch (Exception e) {
                String message="ReConnect not successful "+e.getMessage();
                logit();//etc...
            }
        }

Я не міг знайти іншого способу, оскільки, як ви бачите знизу зображення, ви не можете зрозуміти, втрачено чи ні без зв'язку try and catch, тому що все здається правильно. Цей знімок я отримав, коли отримував Connection resetпостійно.

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


6

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


Це не призвело б до цього виключення самостійно.
Маркіз Лорн

було б, якщо System.exit (0) вбиває програму, і ніхто не викликає socket.close (), оскільки з'єднання в поганому стані та не було закрито належним чином. Sooo правильніше сказав, що у нього є клієнтська програма, яка відключає роботу, не закриваючи розетки;), що погано і потрібно виправити.
Дін Гіллер

1
@DeanHiller Ні, це не буде. Операційна система закривала б сокет так само, як і в додатку.
Маркіз Лорн

@EJP .... Я не впевнений ... Я просто знаю, що ми могли б відтворити його за допомогою System.exit, але я не пам'ятаю ОС / config, як це було досить давно ... виклик socket.close ( ) на сервері не вдалося відновити з'єднання, і воно поводилось більш належним чином.
Дін Гіллер

2
@DeanHiller Процес читання закінчився до того, як процес написання закінчився.
Маркіз Лорн

4

У мене була ця проблема із системою SOA, написаною на Java. Я працював і з клієнтом, і з сервером на різних фізичних машинах, і вони довго працювали нормально, потім ці неприємні скиди з'єднань з’явилися в журналі клієнтів, і в журналі не було нічого дивного. Перезапуск клієнта та сервера не вирішив проблему. Нарешті ми виявили, що купа на стороні сервера досить повна, тому ми збільшили пам’ять, доступну JVM: проблема вирішена! Зауважте, що в журналі не було OutOfMemoryError: пам'ять була лише дефіцитною, не вичерпаною.


2

Перевірте версію Java на сервері. Сталося зі мною, оскільки мій Weblogic 10.3.6 був на JDK 1.7.0_75, який був на TLSv1. Кінцевою точкою решти, яку я намагався споживати, було вимкнення нічого нижче TLSv1.2.

За замовчуванням Weblogic намагався узгодити найсильніший спільний протокол. Докладні відомості див. Тут: Проблеми з налаштуванням https.protocols Властивості системи для HTTPS-з'єднань .

Я додав багатослівний журнал SSL для ідентифікації підтримуваної TLS. Це вказувало, що TLSv1 використовується для рукостискання.
-Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack

Я вирішив це, натиснувши цю функцію на наш сумісний з JDK8 продукт, за замовчуванням JDK8 - TLSv1.2. Для тих, хто обмежений JDK7, я також успішно протестував вирішення Java 7 шляхом оновлення до TLSv1.2. Я використав цю відповідь: Як включити TLS 1.2 в Java 7


велике спасибі, ви показуєте мені новий напрямок, щоб виправити мою проблему. і нарешті я виявив, що це так !!!
karl li

1

У мене також була ця проблема з програмою Java, яка намагалася відправити команду на сервер через SSH. Проблема була в машині, що виконує код Java. У нього не було дозволу на підключення до віддаленого сервера. Метод write () йшов добре, але метод read () кидав java.net.SocketException: Скидання з'єднання. Я вирішив цю проблему, додавши клієнтський ключ SSH до відомих ключів віддаленого сервера.


0

На моєму досвіді я часто стикаюся з такими ситуаціями;

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

  2. Інша проблема полягає в тому, що сертифікат SSL може закінчитися на сервері, де працює ваша програма.

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