简体   繁体   中英

java.net.SocketException: Connection reset by peer: socket write error When serving a file

I am trying to implement an HTTP Server using Sockets. If the Client (For example a browser) requests a directory the server displays a list of available files. The problem arises when the client is requesting a file. I get the following error:

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)

The stacktrace shows that the problem is coming from the writeFile() methods:

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();
}

But I can't figure out what's wrong. Can you help me?

EDIT

Thanks everyone for your answers. After I read your answers I understood that the problem was that the Socket when an error occured. Here's was my wrong 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
    }
}

And my new code was looking like this:

// 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();
        }
    }
}

It is possible for the TCP socket to be "closing" and your code to not have yet been notified.

Here is a animation for the life cycle. http://tcp.cs.st-andrews.ac.uk/index.shtml?page=connection_lifecycle

Basically, the connection was closed by the client. You already have throws IOException and SocketException extends IOException . This is working just fine. You just need to properly handle IOException because it is a normal part of the api.

EDIT: The RST packet occurs when a packet is received on a socket which does not exist or was closed. There is no difference to your application. Depending on the implementation the reset state may stick and closed will never officially occur.

This problem is usually caused by writing to a connection that had already been closed by the peer. In this case it could indicate that the user cancelled the download for example.

I face this problem but resolution is very simple. I am writing the 1 MB file in 1024 Byte Buffer causing this issue. To Understand refer code before and After Fix.

Code with Excepion

DataOutputStream dos = new DataOutputStream(s.getOutputStream());
        FileInputStream fis = new FileInputStream(file);
        byte[] buffer = new byte[1024];
        
        while (fis.read(buffer) > 0) {
            dos.write(buffer);
        }
    

After Fixes:

DataOutputStream dos = new DataOutputStream(s.getOutputStream());
        FileInputStream fis = new FileInputStream(file);
        byte[] buffer = new byte[102400];
        
        while (fis.read(buffer) > 0) {
            dos.write(buffer);
        }

    

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM