J'essaie d'implémenter un serveur HTTP à l'aide de sockets. Si le client (par exemple un navigateur) demande un répertoire, le serveur affiche une liste des fichiers disponibles. Le problème survient lorsque le client demande un fichier. J'obtiens l'erreur suivante:
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)
Le stacktrace montre que le problème vient des méthodes writeFile()
:
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();
}
Mais je ne peux pas comprendre ce qui ne va pas. Pouvez-vous m'aider?
[~ # ~] modifier [~ # ~]
Merci à tous pour vos réponses. Après avoir lu vos réponses, j'ai compris que le problème était que le socket lorsqu'une erreur s'est produite. Voici mon mauvais code:
// 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
}
}
Et mon nouveau code ressemblait à ceci:
// 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();
}
}
}
Il est possible que la socket TCP se "ferme" et que votre code n'ait pas encore été notifié.
Voici une animation pour le cycle de vie. http://tcp.cs.st-andrews.ac.uk/index.shtml?page=connection_lifecycle
Fondamentalement, la connexion a été fermée par le client. Tu as déjà throws IOException
et SocketException
étend IOException
. Cela fonctionne très bien. Vous avez juste besoin de gérer correctement IOException
car c'est une partie normale de l'API.
EDIT: le paquet RST
se produit lorsqu'un paquet est reçu sur un socket qui n'existe pas ou a été fermé. Il n'y a aucune différence dans votre application. Selon l'implémentation, l'état reset
peut rester et closed
ne se produira jamais officiellement.
Ce problème est généralement dû à l'écriture sur une connexion qui a déjà été fermée par l'homologue. Dans ce cas, cela pourrait indiquer que l'utilisateur a annulé le téléchargement par exemple.