java.net.SocketException: Σύνδεση reset

Λαμβάνω το ακόλουθο σφάλμα προσπαθώντας να διαβάσω από μια υποδοχή. Κάνω μια readInt() σε αυτό το InputStream, και λαμβάνω αυτό το σφάλμα. Μελετώντας την τεκμηρίωση αυτό υποδηλώνει ότι το τμήμα πελάτη της σύνδεσης έκλεισε τη σύνδεση. Σε αυτό το σενάριο, εγώ είμαι ο διακομιστής.

Έχω πρόσβαση στα αρχεία καταγραφής του πελάτη και δεν κλείνει τη σύνδεση, και στην πραγματικότητα τα αρχεία καταγραφής του δείχνουν ότι εγώ κλείνω τη σύνδεση. Έχει κανείς μια ιδέα γιατί συμβαίνει αυτό; Τι άλλο να ελέγξω; Μήπως αυτό προκύπτει όταν υπάρχουν τοπικοί πόροι που ίσως φτάνουν σε όρια;


Σημειώνω ότι έχω την ακόλουθη γραμμή: "Ο χρήστης έχει την ακόλουθη γραμμή:":

socket.setSoTimeout(10000);

ακριβώς πριν από την readInt(). Υπάρχει λόγος γι' αυτό (μεγάλη ιστορία), αλλά από περιέργεια, υπάρχουν συνθήκες κάτω από τις οποίες αυτό μπορεί να οδηγήσει στο αναφερόμενο σφάλμα; Έχω τον διακομιστή που τρέχει στο IDE μου, και έτυχε να αφήσω το IDE μου κολλημένο σε ένα σημείο διακοπής, και στη συνέχεια παρατήρησα ότι τα ίδια ακριβώς σφάλματα άρχισαν να εμφανίζονται στα δικά μου αρχεία καταγραφής στο IDE μου.

Εν πάση περιπτώσει, απλά το αναφέρω, ελπίζω να μην είναι μια κόκκινη ρέγγα. :-(

Υπάρχουν διάφορες πιθανές αιτίες.

  1. Το άλλο άκρο έχει μηδενίσει σκόπιμα τη σύνδεση, με τρόπο που δεν θα καταγράψω εδώ. Είναι σπάνιο, και γενικά λανθασμένο, για το λογισμικό εφαρμογών να το κάνει αυτό, αλλά δεν είναι άγνωστο για το εμπορικό λογισμικό.

  2. Συνηθέστερα, προκαλείται από εγγραφή σε μια σύνδεση που το άλλο άκρο έχει ήδη κλείσει κανονικά. Με άλλα λόγια, πρόκειται για σφάλμα του πρωτοκόλλου της εφαρμογής.

  3. Μπορεί επίσης να προκληθεί από το κλείσιμο μιας υποδοχής όταν υπάρχουν μη αναγνωσμένα δεδομένα στο buffer λήψης της υποδοχής.

  4. Στα Windows, η 'διακοπή σύνδεσης που προκαλείται από λογισμικό', η οποία δεν είναι ίδια με την 'επαναφορά σύνδεσης', προκαλείται από προβλήματα δικτύου που αποστέλλονται από την πλευρά σας. Υπάρχει'ένα άρθρο της βάσης γνώσεων της Microsoft σχετικά με αυτό.

Σχόλια (1)

Η επαναφορά σύνδεσης σημαίνει απλώς ότι ελήφθη ένα TCP RST. Αυτό συμβαίνει όταν ο ομότιμος εταίρος σας λαμβάνει δεδομένα που δεν μπορεί να επεξεργαστεί, και μπορεί να υπάρχουν διάφοροι λόγοι γι' αυτό.

Ο απλούστερος είναι όταν κλείνετε την υποδοχή και στη συνέχεια γράφετε περισσότερα δεδομένα στη ροή εξόδου. Κλείνοντας την υποδοχή, είπατε στον ομότιμό σας ότι τελειώσατε με τη συζήτηση και ότι μπορεί να ξεχάσει τη σύνδεσή σας. Όταν στέλνετε περισσότερα δεδομένα σε αυτή τη ροή ούτως ή άλλως, ο ομότιμος το απορρίπτει με ένα RST για να σας ενημερώσει ότι δεν ακούει.

Σε άλλες περιπτώσεις, ένα ενδιάμεσο τείχος προστασίας ή ακόμη και ο ίδιος ο απομακρυσμένος κεντρικός υπολογιστής μπορεί να "ξεχάσει" τη σύνδεσή σας TCP. Αυτό μπορεί να συμβεί αν δεν στείλετε δεδομένα για μεγάλο χρονικό διάστημα (2 ώρες είναι ένα συνηθισμένο χρονικό όριο) ή επειδή ο ομότιμος εταίρος επανεκκινήθηκε και έχασε τις πληροφορίες του σχετικά με τις ενεργές συνδέσεις. Η αποστολή δεδομένων σε μια από αυτές τις ανενεργές συνδέσεις θα προκαλέσει επίσης ένα RST.


Ενημέρωση ως απάντηση σε πρόσθετες πληροφορίες:

Ρίξτε μια προσεκτική ματιά στο χειρισμό της SocketTimeoutException. Αυτή η εξαίρεση εγείρεται αν ξεπεραστεί το διαμορφωμένο χρονικό όριο κατά τη διάρκεια μπλοκαρίσματος σε μια λειτουργία socket. Η κατάσταση της ίδιας της υποδοχής δεν αλλάζει όταν εκπέμπεται αυτή η εξαίρεση, αλλά αν ο χειριστής της εξαίρεσής σας κλείσει την υποδοχή και στη συνέχεια προσπαθήσει να γράψει σε αυτήν, θα βρεθείτε σε κατάσταση επαναφοράς της σύνδεσης. Η setSoTimeout() έχει σκοπό να σας δώσει έναν καθαρό τρόπο να βγείτε από μια λειτουργία read() που διαφορετικά θα μπορούσε να μπλοκάρει για πάντα, χωρίς να κάνετε βρώμικα πράγματα όπως το κλείσιμο του socket από άλλο νήμα.

Σχόλια (2)

Κάθε φορά που είχα περίεργα προβλήματα όπως αυτό, συνήθως κάθομαι με ένα εργαλείο όπως το WireShark και κοιτάζω τα ακατέργαστα δεδομένα που περνούν μπρος-πίσω. Μπορεί να εκπλαγείτε όταν τα πράγματα αποσυνδέονται και σας επισημαίνουν μόνο όταν προσπαθείτε να διαβάσετε.

Σχόλια (0)