Я пытаюсь реализовать HTTP-сервер с помощью Sockets. Если клиент (например, браузер) запрашивает каталог, сервер отображает список доступных файлов. Проблема возникает, когда клиент запрашивает файл. Я получаю следующую ошибку:
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)
Стектура показывает, что проблема исходит из методов 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(); }
Но я не могу понять, что случилось. Вы можете мне помочь?
РЕДАКТИРОВАТЬ
Спасибо всем за ваши ответы. После того, как я прочитал ваши ответы, я понял, что проблема в том, что Socket при возникновении ошибки. Вот мой неправильный код:
// 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 } }
в// 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 } }
И мой новый код выглядел так:
// 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(); } } }
в// 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(); } } }
Возможно, что сокет TCP «закрывается», и ваш код еще не был уведомлен.
Вот анимация для жизненного цикла. http://tcp.cs.st-andrews.ac.uk/index.shtml?page=connection_lifecycle
В принципе, соединение было закрыто клиентом. Вы уже SocketException
throws IOException
и SocketException
расширяет IOException
. Это работает отлично. Вам просто нужно правильно обрабатывать IOException
потому что это нормальная часть api.
EDIT: пакет RST
возникает, когда пакет принимается в сокете, который не существует или был закрыт. Для вашего приложения нет никакой разницы. В зависимости от реализации состояние reset
может closed
и closed
никогда официально не будет.
Эта проблема обычно возникает из-за записи соединения, которое уже было закрыто одноранговым узлом. В этом случае это может означать, что пользователь отменил загрузку, например.