How to replicate a Connection Reset by peer?

7.8k Views Asked by At

I have a server that has the following printed in the log

Caused by: java.io.IOException: Connection reset by peer
        at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
        at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
        at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
        at sun.nio.ch.IOUtil.write(IOUtil.java:65)
        at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
        at org.apache.tomcat.util.net.NioChannel.write(NioChannel.java:134)
        at org.apache.tomcat.util.net.NioBlockingSelector.write(NioBlockingSelector.java:101)
        at org.apache.tomcat.util.net.NioSelectorPool.write(NioSelectorPool.java:157)
        at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.doWrite(NioEndpoint.java:1238)
        at org.apache.tomcat.util.net.SocketWrapperBase.doWrite(SocketWrapperBase.java:670)
        at org.apache.tomcat.util.net.SocketWrapperBase.flushBlocking(SocketWrapperBase.java:607)
        at org.apache.tomcat.util.net.SocketWrapperBase.flush(SocketWrapperBase.java:597)
        at org.apache.coyote.http11.Http11OutputBuffer.flushBuffer(Http11OutputBuffer.java:519)
        at org.apache.coyote.http11.Http11OutputBuffer.flush(Http11OutputBuffer.java:260)
        at org.apache.coyote.http11.Http11Processor.flush(Http11Processor.java:1494)
        at org.apache.coyote.AbstractProcessor.action(AbstractProcessor.java:279)
        at org.apache.coyote.Response.action(Response.java:168)
        at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:317)

I know that the client closed the Connection for some reason, but still the server is writing data. And at this time, the client will return the reset flag "RST", and the server's log will get the Connection reset by peer

To replicate it, I made the server sleep for few seconds and also created a client as such:

 private void executePostMethod() throws IOException, InterruptedException {
        Map<String, String> responseMap = new HashMap<>();
        String data = "{\"id\":\"XYZ123\",\"name\":\"John Doe\",\"accountNumber\":\"ABC123\"}";
        URL urlObject = new URL("\"http://localhost/v1/name/validate\"");
        System.out.println("Creating Connection");
        Socket socket = new Socket(InetAddress.getByName(urlObject.getHost()), 7080);
        System.out.println("Connection Established");

        PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
        printWriter.println("POST " + urlObject.getFile() + " HTTP/1.0");
        printWriter.println("Host: " + urlObject.getHost());
        printWriter.println("Content-Length: " + data.length());
        printWriter.println("Content-Type: " + "application/json");
        printWriter.println();   //Writing an empty line just to notify the server the header ends here
        // and next thing written will the data/content
        printWriter.println(data);
        printWriter.println();
        printWriter.flush();
        Thread.sleep(5000);
        socket.setSoLinger(true, 0);
        socket.close();
    }

Before the server sends the response, the close the socket and the line socket.setSoLinger(true, 0); I believe, sends the RST packet. But I get the org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe error instead of Connection reset by peer.

How to reproduce java.io.IOException: Connection reset by peer ?

UPDATE

I analyzed the TCP connection and this is what I got. The server receives the RST packet before it tries to send the data to the client

enter image description here

Now from what I know, if the client sends RST packet to the server, the server gets Connection reset by peer , all I get it Broken pipe.

2

There are 2 best solutions below

0
On

This might be of help to anyone trying to figure out the error and its cause.

The above mentioned program does work, but I found out that it is server dependent. I tried the above code in a different server and I got

Caused by: java.io.IOException: Connection reset by peer
1
On

This client/server example replicates it:

import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

public class Test {
    private static final int port = 1234;
    public static void main(String[] args) throws Exception {
        if (args.length == 1) { // client
            final Socket socket = new Socket(args[0], port);
            socket.setSoLinger(true, 0);
            socket.close();
        } else { // server
            ServerSocketChannel serverSocket = ServerSocketChannel.open();
            serverSocket.socket().bind(new InetSocketAddress(port));
            SocketChannel client = serverSocket.accept();
            client.read(ByteBuffer.allocate(1));
        }
    }
}

To wit:

$ java Test.java &         # start the server
$ java Test.java 127.0.0.1 # start the client
Exception in thread "main" java.io.IOException: Connection reset by peer
        at java.base/sun.nio.ch.FileDispatcherImpl.read0(Native Method)
        at java.base/sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39)
        at java.base/sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:276)
        at java.base/sun.nio.ch.IOUtil.read(IOUtil.java:245)
        at java.base/sun.nio.ch.IOUtil.read(IOUtil.java:223)
        at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:353)
        at Test.main(Test.java:18)
[1]+  Exit 1                  java Test.java