java.net.SocketException: Connection reset

Es saņemu šādu kļūdu, mēģinot nolasīt no ligzdas. Es veicu readInt() uz šī InputStream, un es saņemu šo kļūdu. Izlasot dokumentāciju, var secināt, ka savienojuma klienta daļa ir slēgusi savienojumu. Šajā scenārijā es esmu serveris.

Man ir piekļuve klienta žurnāla failiem, un tas savienojumu neaizver, un patiesībā tā žurnāla faili liecina, ka es slēdzu savienojumu. Vai kādam ir kāda ideja, kāpēc tā notiek? Kas vēl jāpārbauda? Vai tā rodas, ja ir vietējie resursi, kas, iespējams, sasniedz robežvērtības?


Es ievēroju, ka man ir šāda rinda:

socket.setSoTimeout(10000);

tieši pirms readInt(). Tam ir iemesls (garš stāsts), bet tikai interesanti, vai ir apstākļi, kādos tas varētu izraisīt norādīto kļūdu? Serveris darbojas manā IDE, un man gadījās atstāt IDE iesprūdušu uz pārtraukuma punkta, un tad es pamanīju, ka tieši tādas pašas kļūdas sāk parādīties manos IDE žurnālos.

Jebkurā gadījumā, tikai pieminēju to, cerams, ka tas nav sarkana siļķe. :-(

Ir vairāki iespējamie iemesli.

  1. Otra puse ir apzināti atiestatījusi savienojumu tādā veidā, ko es šeit nedokumentēšu. Lietojumprogrammatūra to dara reti un parasti nepareizi, taču komerciālai programmatūrai tas nav svešs gadījums.

  2. Biežāk to izraisa rakstīšana uz savienojuma, kuru otra puse jau ir normāli slēgusi. Citiem vārdiem sakot, lietojumprogrammas protokola kļūda.

  3. To var izraisīt arī savienojuma slēgšana, ja savienojuma saņemšanas buferī ir neizlasīti dati.

  4. Windows operētājsistēmā 'programmatūras izraisīta savienojuma pārtraukšana', kas nav tas pats, kas 'savienojuma atiestatīšana', rodas tīkla problēmu dēļ, sūtot no jūsu puses. Par to ir Microsoft zināšanu bāzes raksts.

Komentāri (1)

Savienojuma atiestatīšana vienkārši nozīmē, ka ir saņemts TCP RST. Tas notiek, kad jūsu partneris saņem datus, kurus tas nevar apstrādāt, un tam var būt dažādi iemesli.

Vienkāršākais ir tad, ja jūs aizverat ligzdu un pēc tam ierakstāt vairāk datu izejas plūsmā. Aizverot ligzdu, jūs paziņojāt savam vienaudzim, ka esat beidzis sarunu, un tas var aizmirst par jūsu savienojumu. Kad jūs tik un tā sūtāt vairāk datu uz šo plūsmu, vienādranga partneris tos noraida ar RST, lai jūs zinātu, ka tas neklausās.

Citos gadījumos starpnieks ugunsmūris vai pat pats attālais resursdators var "aizmirst" par jūsu TCP savienojumu. Tas var notikt, ja jūs ilgu laiku nenosūtāt datus (2 stundas ir parasta laika pauze) vai arī tāpēc, ka partneris tika restartēts un zaudēja informāciju par aktīvajiem savienojumiem. Nosūtot datus uz kādu no šiem neaktīvajiem savienojumiem, arī tiks nosūtīts RST.


Atjauninājums, atbildot uz papildu informāciju:

Rūpīgi aplūkojiet, kā rīkojaties ar SocketTimeoutException. Šis izņēmums tiek radīts, ja, bloķējot ligzdas operāciju, tiek pārsniegts konfigurētais laika limits. Pats ligzdas stāvoklis nemainās, kad šis izņēmums tiek izmests, bet, ja jūsu izņēmuma apstrādātājs slēdz ligzdu un pēc tam mēģina uz to rakstīt, jūs nokļūsiet savienojuma atiestatīšanas stāvoklī. setSoTimeout() ir domāts, lai sniegtu jums tīru veidu, kā pārtraukt lasīšanas() operāciju, kas citādi varētu bloķēties uz visiem laikiem, neveicot tādas netīras darbības kā ligzdas slēgšana no cita pavediena.

Komentāri (2)

Kad man ir bijušas šādas neparastas problēmas, es parasti izmantoju tādu rīku kā WireShark un aplūkoju neapstrādātus datus, kas tiek nodoti turp un atpakaļ. Jūs varētu būt pārsteigts, kur viss tiek atvienots, un jūs par to tiekat informēts tikai tad, kad mēģināt nolasīt.

Komentāri (0)