2014-09-01 20 views
9

Sto cercando di implementare un server HTTP tramite Sockets. Se il client (ad esempio un browser) richiede una directory, il server visualizza un elenco di file disponibili. Il problema sorge quando il client richiede un file. Ottengo il seguente errore:java.net.SocketException: Connessione ripristinata dal peer: errore di scrittura socket Quando si serve un file

java.net.SocketException: Connection reset by peer: socket write error 
at java.net.SocketOutputStream.socketWrite0(Native Method) 
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113) 
at java.net.SocketOutputStream.write(SocketOutputStream.java:159) 
at cf.charly1811.java.web.RequestHandler.writeFile(RequestHandler.java:152) 
at cf.charly1811.java.web.RequestHandler.processRequest(RequestHandler.java:139) 
at cf.charly1811.java.web.RequestHandler.handleRequest(RequestHandler.java:110) 
at cf.charly1811.java.web.RequestHandler.run(RequestHandler.java:86) 
at java.lang.Thread.run(Thread.java:745) 

La StackTrace dimostra che il problema è in arrivo dalle writeFile() metodi:

private void writeFile(File request) throws IOException 
{ 
    InputStream byteReader = new BufferedInputStream(new FileInputStream(request)); 
    byte[] buffer = new byte[1024]; 
    int bytesRead; 
    while ((bytesRead = byteReader.read(buffer)) != -1) 
    { 
     outputStream.write(buffer, 0, bytesRead); 
    } 
    byteReader.close(); 
} 

Ma io non riesco a capire cosa c'è che non va. Potete aiutarmi?

EDIT

Grazie a tutti per le vostre risposte. Dopo aver letto le tue risposte ho capito che il problema era il socket quando si verificava un errore. Qui di stato il mio codice errato:

// Method to process a single request 
handleRequest() throw IOException 
{ 
    // process here 
    // if the client request a file 
    writeFile(); 
    // close socket when the request is processed 
} 

// The method is called 
public run() 
{ 
    try{ 
     // If an error occurs the try/catch won't be called because it is implemented outside the loop. So when an IOException occurs, the loop just stop and exit the program 
     while(true) 
     { 
      handleRequest(); 
     } 
    } 
    catch(IOException e) { 
     // Handle exception here 
    } 
} 

e il mio nuovo codice era simile a questo:

// Method to process a single request 
handleRequest() 
{ 
    try { 
     // process here 
     // if the client request a file 
     writeFile(); 
     // close socket when the request is processed 
    } 
    // If this exception occurs the catch() method will be called 
    catch(IOException e) 
    { 
     // handle exception here 
    } 
} 

// The method is called 
public run() 
{ 
    while(true) 
     { 
      handleRequest(); 
     } 
    } 
} 
+1

Probabilmente è necessario esaminare cosa sta accadendo sull'host remoto (il "clent"). SUGGERIMENTO: provare [Wireshark] (http://www.wireshark.org). – FoggyDay

+0

Il ciclo 'while (true)' deve uscire normalmente quando si verifica una IOException. Il nuovo codice nella modifica ha un nuovo problema in cui il ciclo 'while' sta per girare per sempre se il socket si chiude in modo anomalo. – bond

+0

@baconoverlord cosa consiglia per questo? –

risposta

11

È possibile che il socket TCP "si chiuda" e che il codice non sia stato ancora notificato.

Ecco un'animazione per il ciclo di vita. http://tcp.cs.st-andrews.ac.uk/index.shtml?page=connection_lifecycle

Fondamentalmente, la connessione è stata chiusa dal client. Hai già throws IOException e SocketException estende IOException. Questo sta funzionando bene. Hai solo bisogno di gestire correttamente IOException perché è una parte normale della api.

MODIFICA: il pacchetto RST si verifica quando un pacchetto viene ricevuto su un socket che non esiste o è stato chiuso. Non c'è differenza per la tua applicazione. A seconda dell'implementazione, lo stato reset potrebbe rimanere bloccato e closed non si verificherà mai ufficialmente.

+0

È possibile che la * porta * sia 'CLOSING', ma questo stato non ha nulla a che fare con questa domanda.Significa che entrambe le estremità si sono chiuse contemporaneamente, nel qual caso questa scrittura genererebbe un'eccezione 'socket closed'. – EJP

+0

Dice 'reset da peer: errore di scrittura socket '. I pacchetti di ripristino 'RST' si verificano quando una destinazione ha ricevuto un pacchetto per un socket chiuso. Una delle due estremità ha interrotto la connessione in modo anomalo o semplicemente stava succedendo così velocemente (magari in loopback) che questo si verifica a metà chiusura. Ho visto questo errore abbastanza spesso per sapere che tutte le IOException su 'write()' devono essere gestite come se la connessione fosse chiusa. – bond

+0

@EJP ha tutto a che fare con la domanda. Ho cercato di spiegare il ciclo di vita oltre la tua risposta di "connessione che era già stata chiusa dal pari". Lo stesso errore dice "reset by peer". Non dovresti minimizzare le persone che lavorano con le prese ogni giorno e hanno visto ogni possibile tipo di condizione di stato medio immaginabile su tutti i principali sistemi operativi in ​​produzione. – bond

1

Questo problema è di solito causata da scrivere a una connessione che era già stata chiusa dal peer. In questo caso potrebbe indicare che l'utente ha annullato il download, ad esempio.

Problemi correlati