java.net.SocketException: Connection reset

Bandydamas skaityti iš lizdo gaunu tokią klaidą. Atlieku readInt() ant to InputStream ir gaunu šią klaidą. Nagrinėjant dokumentaciją galima daryti prielaidą, kad klientinė ryšio dalis uždarė ryšį. Šiame scenarijuje aš esu serveris.

Turiu prieigą prie kliento žurnalo failų ir jis neuždaro ryšio, o iš tikrųjų jo žurnalo failai rodo, kad ryšį uždarau aš. Ar kas nors numano, kodėl taip atsitinka? Ką dar reikėtų patikrinti? Ar taip nutinka, kai yra vietinių išteklių, kurie galbūt pasiekia ribas?


Atkreipiu dėmesį, kad turiu tokią eilutę:

socket.setSoTimeout(10000);

prieš pat readInt(). Tam yra priežastis (ilga istorija), bet tiesiog smalsu, ar yra aplinkybių, dėl kurių tai gali sukelti nurodytą klaidą? Mano IDE veikia serveris, ir atsitiko taip, kad palikau IDE užstrigusį pertraukos tašką, ir tada pastebėjau, kad mano IDE žurnaluose pradėjo rodytis lygiai tokios pačios klaidos.

Bet kokiu atveju, tiesiog paminėjau tai, tikiuosi, kad tai nėra raudona silkė. :-(

Galimos kelios priežastys.

  1. Kita pusė sąmoningai iš naujo nustatė ryšį tokiu būdu, kurio čia nekomentuosiu. Tai retai ir paprastai neteisingai daro taikomoji programinė įranga, tačiau tai nėra nežinoma komercinei programinei įrangai.

  2. Dažniau taip nutinka dėl to, kad rašoma į jungtį, kurią kita pusė jau normaliai uždarė. Kitaip tariant, taikomosios programos protokolo klaida.

  3. Ji taip pat gali būti sukelta uždarant lizdą, kai lizdo priėmimo buferyje yra neperskaitytų duomenų.

  4. Windows sistemoje 'programinės įrangos sukeltas ryšio nutraukimas', kuris nėra tas pats, kas 'ryšio atstatymas', atsiranda dėl tinklo problemų siunčiant iš jūsų pusės. Apie tai'yra "Microsoft" žinių bazės straipsnis.

Komentarai (1)

Ryšio atstatymas reiškia, kad buvo gautas TCP RST. Taip atsitinka, kai jūsų bendrakeleivis gauna duomenis, kurių negali apdoroti, o to priežastys gali būti įvairios.

Paprasčiausia, kai uždarote lizdą, o tada į išvesties srautą įrašote daugiau duomenų. Uždarydami lizdą pranešėte savo bendrakeleiviui, kad baigėte pokalbį, ir jis gali pamiršti apie jūsų ryšį. Kai vis tiek siunčiate daugiau duomenų į tą srautą, bendrakeleivis juos atmeta su RST, kad praneštų, jog jūsų neklauso.

Kitais atvejais tarpinė ugniasienė arba net pats nuotolinis kompiuteris gali pamiršti apie jūsų TCP ryšį. Taip gali atsitikti, jei ilgą laiką nesiunčiate jokių duomenų (įprastas laiko tarpas - 2 valandos) arba jei bendrakeleivis buvo perkrautas ir prarado informaciją apie aktyvius ryšius. Siunčiant duomenis vienu iš tokių neveikiančių ryšių taip pat bus siunčiamas RST.


Atnaujinta gavus papildomos informacijos:

Atidžiai išnagrinėkite, kaip elgiatės su SocketTimeoutException. Ši išimtis sukeliama, jei užblokuojant lizdo operaciją viršijamas nustatytas laiko limitas. Paties lizdo būsena nepasikeičia, kai išmetama ši išimtis, tačiau jei jūsų išimties tvarkytojas uždaro lizdą, o paskui bando į jį rašyti, jūs' pateksite į ryšio atstatymo būseną. SetSoTimeout() yra skirtas tam, kad galėtumėte švariai nutraukti skaitymo() operaciją, kuri priešingu atveju gali užsiblokuoti amžinai, nedarydami tokių nešvarių dalykų, kaip lizdo uždarymas iš kitos gijos.

Komentarai (2)

Kai susiduriu su tokiomis keistomis problemomis, paprastai atsisėdu su tokia priemone kaip WireShark ir pasižiūriu į neapdorotus duomenis, perduodamus pirmyn ir atgal. Galite nustebti, kur viskas yra atjungiama, o jums apie tai pranešama tik tada, kai bandote skaityti.

Komentarai (0)