-
Bug
-
Resolution: Unresolved
-
P3
-
None
-
11.0.27, 24.0.2
-
x86_64
-
windows
A DESCRIPTION OF THE PROBLEM :
Receiving connection reset error on client end when socket.close() is called.
Steps
- One thread runs through out application lifetime, whose purpose is to accept the incoming socket connection. (similar code gist as ServerThread.class attached)
- After accepting the socket connection a new thread is created and handed over with the accepted socket. The new thread uses the socket input and output stream to read and write data.
- Some other thread can decide based on circumstances to terminate the socket using socket.close().
When socket.close() is called:
Java 11: On socket.close() call, sends RST packet to the client, thus connection reset error on client end.
Java 8: On socket.close() call, sends FIN packet to the client, thus no issue observed on client end.
Note: Please ignore the thread sleep and all sort of duppy code attached. Its just for issue reproduction purpose. The real application is a proxy kinda server which accepts connection and forwards data to some other connection. The other connection once done with data instructs to close the accepted connection.
REGRESSION : Last worked in version 8
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the provided sample code(test case code) in Java 8 and Java 11 to see the connection reset error.
Three class:
ServerThread.class
Client.class
Main.class
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Connection reset error should not appear as there is no data to read
ACTUAL -
Connection reset error
---------- BEGIN SOURCE ----------
// server thread class
import java.net.*;
import java.io.*;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.Set;
public class ServerThread extends Thread {
private final int port;
private Socket s = null;
private InputStream in = null;
// Constructor with port
public ServerThread(int port) {
this.port = port;
}
public Socket getSocket() {
return this.s;
}
public void run() {
// Starts server and accept connection
try {
Selector socketSelector = SelectorProvider.provider().openSelector();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", port);
serverSocketChannel.socket().bind(inetSocketAddress);
serverSocketChannel.register(socketSelector, SelectionKey.OP_ACCEPT);
socketSelector.select();
Set<SelectionKey> selectedKeys = socketSelector.selectedKeys();
for (SelectionKey selectionKey : selectedKeys) {
if (selectionKey.isAcceptable()) {
ServerSocketChannel sSC =
(ServerSocketChannel) selectionKey.channel();
// Accept the connection
SocketChannel socketChannel = sSC.accept();
s = socketChannel.socket();
System.out.println("Client accepted");
s.setKeepAlive(true);
s.setTcpNoDelay(true);
// Takes input from the client socket
in = s.getInputStream();
int m = 0;
// Reads message from client
while (m != -1) {
try {
m = in.read(new byte[16]);
System.out.println(m);
} catch (IOException i) {
System.out.println("Got exception in server thread: " + i);
break;
}
}
System.out.println("Closing connection");
}
}
selectedKeys.clear();
} catch (IOException i) {
System.out.println("Got from server thread " + i);
}
}
}
--------------------------------------------------------------------------------------
// client class
import java.io .*;
import java.net .*;
public class Client {
private Socket s = null;
private InputStream in = null;
// Constructor to put IP address and port
public Client(String addr, int port) {
// Establish a connection
try {
s = new Socket(addr, port);
in = s.getInputStream();
System.out.println("Connected");
} catch (UnknownHostException u) {
System.out.println(u);
return;
} catch (IOException i) {
System.out.println(i);
return;
}
// String to read message from input
//String m = "";
int m = 0;
// Keep reading until "Over" is input
while (m != -1) {
try {
m = in.read(new byte[16]);
System.out.println(m);
} catch (IOException i) {
System.out.println("Got exception in client: " + i);
break;
}
}
// Close the connection
try {
s.close();
} catch (IOException i) {
System.out.println(i);
}
}
}
-------------------------------------------------------------------------------------
// main class
import java.io.IOException;
public class Main {
public static void main(String[] args) {
ServerThread s = new ServerThread(5000);
s.start();
Thread t = new Thread(() -> {
try {
Thread.sleep(10000);
s.getSocket().close();
} catch (IOException e) {
System.out.println("Got IO exception");
} catch (InterruptedException e) {
System.out.println("Got InterruptedException");
}
});
t.start();
Thread t1 = new Thread(() -> {
try {
Thread.sleep(5000);
Client c = new Client("127.0.0.1", 5000);
} catch (InterruptedException e) {
System.out.println("Got InterruptedException");
}
});
t1.start();
}
}
---------- END SOURCE ----------
Receiving connection reset error on client end when socket.close() is called.
Steps
- One thread runs through out application lifetime, whose purpose is to accept the incoming socket connection. (similar code gist as ServerThread.class attached)
- After accepting the socket connection a new thread is created and handed over with the accepted socket. The new thread uses the socket input and output stream to read and write data.
- Some other thread can decide based on circumstances to terminate the socket using socket.close().
When socket.close() is called:
Java 11: On socket.close() call, sends RST packet to the client, thus connection reset error on client end.
Java 8: On socket.close() call, sends FIN packet to the client, thus no issue observed on client end.
Note: Please ignore the thread sleep and all sort of duppy code attached. Its just for issue reproduction purpose. The real application is a proxy kinda server which accepts connection and forwards data to some other connection. The other connection once done with data instructs to close the accepted connection.
REGRESSION : Last worked in version 8
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the provided sample code(test case code) in Java 8 and Java 11 to see the connection reset error.
Three class:
ServerThread.class
Client.class
Main.class
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Connection reset error should not appear as there is no data to read
ACTUAL -
Connection reset error
---------- BEGIN SOURCE ----------
// server thread class
import java.net.*;
import java.io.*;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.Set;
public class ServerThread extends Thread {
private final int port;
private Socket s = null;
private InputStream in = null;
// Constructor with port
public ServerThread(int port) {
this.port = port;
}
public Socket getSocket() {
return this.s;
}
public void run() {
// Starts server and accept connection
try {
Selector socketSelector = SelectorProvider.provider().openSelector();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", port);
serverSocketChannel.socket().bind(inetSocketAddress);
serverSocketChannel.register(socketSelector, SelectionKey.OP_ACCEPT);
socketSelector.select();
Set<SelectionKey> selectedKeys = socketSelector.selectedKeys();
for (SelectionKey selectionKey : selectedKeys) {
if (selectionKey.isAcceptable()) {
ServerSocketChannel sSC =
(ServerSocketChannel) selectionKey.channel();
// Accept the connection
SocketChannel socketChannel = sSC.accept();
s = socketChannel.socket();
System.out.println("Client accepted");
s.setKeepAlive(true);
s.setTcpNoDelay(true);
// Takes input from the client socket
in = s.getInputStream();
int m = 0;
// Reads message from client
while (m != -1) {
try {
m = in.read(new byte[16]);
System.out.println(m);
} catch (IOException i) {
System.out.println("Got exception in server thread: " + i);
break;
}
}
System.out.println("Closing connection");
}
}
selectedKeys.clear();
} catch (IOException i) {
System.out.println("Got from server thread " + i);
}
}
}
--------------------------------------------------------------------------------------
// client class
import java.io .*;
import java.net .*;
public class Client {
private Socket s = null;
private InputStream in = null;
// Constructor to put IP address and port
public Client(String addr, int port) {
// Establish a connection
try {
s = new Socket(addr, port);
in = s.getInputStream();
System.out.println("Connected");
} catch (UnknownHostException u) {
System.out.println(u);
return;
} catch (IOException i) {
System.out.println(i);
return;
}
// String to read message from input
//String m = "";
int m = 0;
// Keep reading until "Over" is input
while (m != -1) {
try {
m = in.read(new byte[16]);
System.out.println(m);
} catch (IOException i) {
System.out.println("Got exception in client: " + i);
break;
}
}
// Close the connection
try {
s.close();
} catch (IOException i) {
System.out.println(i);
}
}
}
-------------------------------------------------------------------------------------
// main class
import java.io.IOException;
public class Main {
public static void main(String[] args) {
ServerThread s = new ServerThread(5000);
s.start();
Thread t = new Thread(() -> {
try {
Thread.sleep(10000);
s.getSocket().close();
} catch (IOException e) {
System.out.println("Got IO exception");
} catch (InterruptedException e) {
System.out.println("Got InterruptedException");
}
});
t.start();
Thread t1 = new Thread(() -> {
try {
Thread.sleep(5000);
Client c = new Client("127.0.0.1", 5000);
} catch (InterruptedException e) {
System.out.println("Got InterruptedException");
}
});
t1.start();
}
}
---------- END SOURCE ----------