java.net.SocketException: reimpostazione della connessione


128

Ricevo il seguente errore durante la lettura da un socket. Sto facendo unreadInt() su questo InputStreame ricevo questo errore. Esaminando la documentazione questo suggerisce che la parte client della connessione ha chiuso la connessione. In questo scenario, io sono il server.

Ho accesso ai file di registro del client e non sta chiudendo la connessione, infatti i suoi file di registro suggeriscono che sto chiudendo la connessione. Qualcuno ha un'idea del perché sta accadendo? Cos'altro controllare? Ciò si verifica quando ci sono risorse locali che stanno forse raggiungendo le soglie?


Prendo atto che ho la seguente riga:

socket.setSoTimeout(10000);

appena prima del readInt(). C'è una ragione per questa (lunga storia), ma solo curioso, ci sono circostanze in cui ciò potrebbe portare all'errore indicato? Ho il server in esecuzione nel mio IDE e mi è capitato di lasciare il mio IDE bloccato su un punto di interruzione, quindi ho notato che gli stessi identici errori iniziano ad apparire nei miei log nel mio IDE.

Comunque, solo menzionarlo, si spera non una falsa pista. :-(


Hai tracce di pila da entrambi i lati? Puoi descrivere un po 'di più l'architettura di rete? (Su Internet selvaggio? Sulla stessa macchina? Da qualche parte nel mezzo?) Succede tutto il tempo? O a intermittenza?
Stu Thompson

Risposte:


116

Ci sono diverse possibili cause.

  1. L'altra estremità ha deliberatamente ripristinato la connessione, in un modo che non documenterò qui. È raro e generalmente errato che il software applicativo lo faccia, ma non è sconosciuto per il software commerciale.

  2. Più comunemente, è causato dalla scrittura su una connessione che l'altra estremità ha già chiuso normalmente. In altre parole, un errore del protocollo dell'applicazione.

  3. Può anche essere causato dalla chiusura di un socket quando sono presenti dati non letti nel buffer di ricezione del socket.

  4. In Windows, "il software ha causato l'interruzione della connessione", che non è la stessa cosa di "ripristino della connessione", è causato da problemi di rete che inviano dalla tua parte. C'è un articolo della Knowledge Base di Microsoft su questo.


@ MattLyons Grazie. Ci sono articoli MSDN molto migliori di quello. Francamente lo trovo difficile da credere. Una connessione non esisterà nemmeno fino a quando non saranno stati stabiliti gli indirizzi IP di origine e di destinazione corretti. Gli articoli MSDN che ho visto fanno riferimento a errori di rete persistenti che scadono la connessione.
Marchese di Lorne

48

Il ripristino della connessione significa semplicemente che è stato ricevuto un RST TCP. Ciò accade quando il tuo peer riceve dati che non può elaborare e ci possono essere vari motivi per questo.

Il più semplice è chiudere il socket e quindi scrivere più dati nel flusso di output. Chiudendo la presa, hai detto al tuo collega che hai finito di parlare e che può dimenticare la tua connessione. Quando invii comunque più dati su quel flusso, il peer lo rifiuta con un RST per farti sapere che non sta ascoltando.

In altri casi, un firewall che interviene o anche lo stesso host remoto potrebbe "dimenticare" la connessione TCP. Ciò potrebbe accadere se non si inviano dati per un lungo periodo (2 ore è un timeout comune) o perché il peer è stato riavviato e ha perso le informazioni sulle connessioni attive. L'invio di dati su una di queste connessioni inattive causerà anche un RST.


Aggiornamento in risposta a ulteriori informazioni:

Dai un'occhiata da vicino alla tua gestione del file SocketTimeoutException. Questa eccezione viene sollevata se il timeout configurato viene superato durante il blocco su un'operazione socket. Lo stato del socket stesso non viene modificato quando viene generata questa eccezione, ma se il gestore di eccezioni chiude il socket e quindi prova a scriverci, sarai in una condizione di ripristino della connessione. setSoTimeout()ha lo scopo di darti un modo pulito per uscire da read()un'operazione che altrimenti potrebbe bloccarsi per sempre, senza fare cose sporche come chiudere il socket da un altro thread.


Non corretto sotto diversi aspetti. La raccolta dei rifiuti e le uscite dal processo causano entrambe le chiusure corrette, non ripristini, ma una chiusura seguita da una scrittura da parte del peer può indurre un ripristino piuttosto che un EOS. SocketTimeoutExceptions vengono sollevate solo se il lettore ha impostato un timeout di lettura.
Marchese di Lorne

E non sempre significa che è stato ricevuto un RST. Può anche significare che uno è stato generato da questo lato.
Marchese di Lorne

17

Ogni volta che ho avuto problemi strani come questo, di solito mi siedo con uno strumento come WireShark e guardo i dati grezzi che vengono passati avanti e indietro. Potresti essere sorpreso di dove le cose vengono disconnesse e ti viene notificato solo quando provi a leggere.


9

Imbarazzante dirlo, ma quando ho avuto questo problema, è stato semplicemente un errore chiudere la connessione prima di leggere tutti i dati. Nei casi in cui venivano restituite piccole stringhe, funzionava, ma probabilmente era dovuto al fatto che l'intera risposta era stata bufferizzata, prima di chiuderla.

Nei casi in cui venivano restituite quantità di testo più lunghe, veniva generata l'eccezione, poiché più di un buffer stava tornando.

Potresti controllare questa svista. Ricorda che l'apertura di un URL è come un file, assicurati di chiuderlo (rilascia la connessione) una volta che è stato letto completamente.


9

Dovresti ispezionare la traccia completa con molta attenzione,

Ho un'applicazione socket del server e ho risolto un java.net.SocketException: Connection resetcaso.

Nel mio caso accade durante la lettura da un Socketoggetto clientSocket che ha chiuso la sua connessione per qualche motivo. (Rete persa, firewall o arresto anomalo dell'applicazione o chiusura intenzionale)

In realtà stavo ristabilendo la connessione quando ho ricevuto un errore durante la lettura da questo oggetto Socket.

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

La cosa interessante è che for my JAVA Socketse un client si connette a my ServerSockete chiude la sua connessione senza inviare nulla is.read()chiama se stesso in modo ricorsivo. Sembra che a causa di un ciclo while infinito per la lettura da questo socket provi a leggere da una connessione chiusa. Se usi qualcosa di simile sotto per l'operazione di lettura;

while(true)
{
  Receive();
}

Quindi ottieni uno stackTrace qualcosa come di seguito avanti e indietro

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

Quello che ho fatto è stato semplicemente chiudere ServerSocket e rinnovare la mia connessione e attendere ulteriori connessioni client in arrivo

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


//...
}

Ciò ristabilisce la mia connessione per le perdite di socket client sconosciute

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...
            }
        }

Non sono riuscito a trovare un altro modo perché come vedi dall'immagine sotto non puoi capire se la connessione è persa o meno senza un try and catch, perché tutto sembra a posto. Ho ottenuto questa istantanea mentre stavo ottenendo Connection resetcontinuamente.

inserisci qui la descrizione dell'immagine


6

Ho avuto lo stesso errore. Ho trovato la soluzione per il problema ora. Il problema era che il programma client stava terminando prima che il server leggesse i flussi.


Ciò non causerebbe questa eccezione da solo.
Marchese di Lorne

lo sarebbe se System.exit (0) uccidesse il programma e nessuno chiamasse socket.close () poiché la connessione è in cattivo stato e non è stata chiusa correttamente. così più correttamente ha detto che aveva un programma client che si chiudeva senza chiudere i socket;) che è una cosa negativa e dovrebbe essere risolta.
Dean Hiller

1
@ DeanHiller No, non lo sarebbe. Il sistema operativo chiuderebbe il socket nello stesso modo in cui dovrebbe avere l'applicazione.
Marchese di Lorne

@EJP .... non sono sicuro ... so solo che potremmo riprodurlo con System.exit ma non ricordo il sistema operativo / config dato che era un po 'di tempo fa .... chiamando socket.close ( ) sul server ha impedito il ripristino della connessione e si è comportato in modo più corretto.
Dean Hiller

2
@DeanHiller Il processo di lettura è terminato prima che il processo di scrittura avesse finito di scrivere.
Marchese di Lorne

4

Ho avuto questo problema con un sistema SOA scritto in Java. Stavo eseguendo sia il client che il server su diverse macchine fisiche e hanno funzionato bene per molto tempo, poi quei brutti ripristini della connessione sono apparsi nel registro del client e non c'era niente di strano nel registro del server. Il riavvio di client e server non ha risolto il problema. Finalmente abbiamo scoperto che l'heap lato server era piuttosto pieno quindi abbiamo aumentato la memoria a disposizione della JVM: problema risolto! Nota che non c'era OutOfMemoryError nel log: la memoria era solo scarsa, non esaurita.


2

Controlla la versione Java del tuo server. Mi è successo perché il mio Weblogic 10.3.6 era su JDK 1.7.0_75 che era su TLSv1. Il resto dell'endpoint che stavo cercando di consumare stava chiudendo qualsiasi cosa al di sotto di TLSv1.2.

Per impostazione predefinita, Weblogic stava cercando di negoziare il protocollo condiviso più potente. Vedere i dettagli qui: Problemi con l'impostazione della proprietà di sistema https.protocols per le connessioni HTTPS .

Ho aggiunto la registrazione SSL dettagliata per identificare il TLS supportato. Ciò indicava che TLSv1 veniva utilizzato per l'handshake.
-Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack

Ho risolto questo problema trasferendo la funzione al nostro prodotto compatibile con JDK8, JDK8 è impostato su TLSv1.2. Per quelli limitati a JDK7, ho anche testato con successo una soluzione alternativa per Java 7 aggiornando a TLSv1.2. Ho usato questa risposta: come abilitare TLS 1.2 in Java 7


molte grazie, mi mostri una nuova direzione per risolvere il mio problema. e finalmente ho scoperto che è così !!!
karl li

1

Ho anche avuto questo problema con un programma Java che cercava di inviare un comando su un server tramite SSH. Il problema era con la macchina che eseguiva il codice Java. Non aveva il permesso di connettersi al server remoto. Il metodo write () stava andando bene, ma il metodo read () lanciava un'eccezione java.net.SocketException: Connection reset. Ho risolto questo problema aggiungendo la chiave SSH del client alle chiavi note del server remoto.


0

Nella mia esperienza, incontro spesso le seguenti situazioni;

  1. Se lavori in un'azienda aziendale, contatta il team di rete e sicurezza. Perché nelle richieste effettuate a servizi esterni, potrebbe essere necessario fornire l'autorizzazione per l'endpoint pertinente.

  2. Un altro problema è che il certificato SSL potrebbe essere scaduto sul server in cui è in esecuzione l'applicazione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.