When a connected netty client is forced closed, the netty server will detect the close action and throw IOException:
java.io.IOException: 远程主机强迫关闭了一个现有的连接(In English: the remote host forcely closed an existing connection)。
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
at sun.nio.ch.IOUtil.read(IOUtil.java:192)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:378)
at io.netty.buffer.PooledUnsafeDirectByteBuf.setBytes(PooledUnsafeDirectByteBuf.java:288)
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1108)
at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:345)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:148)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
But as a lot of answers (Detecting socket disconnection?) say, nio server it self can not detect client close action, unless it send message throw the broken connection.
Below code is a sample for testing the client close action for java nio. When the client is closed, on the server side the registered socket channel will not be closed and its key will not be removed.
Nio server, simply accept connection and print what received.
public class Server {
public static void main(String[] args) throws IOException, InterruptedException {
Selector selector = Selector.open();
ServerSocketChannel serverSocket = ServerSocketChannel.open();
serverSocket.bind(new InetSocketAddress("localhost", 5454));
serverSocket.configureBlocking(false);
serverSocket.register(selector, SelectionKey.OP_ACCEPT);
ByteBuffer buffer = ByteBuffer.allocate(16);
while (true) {
Thread.sleep(3000);
selector.select();
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> iter = selectedKeys.iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
if (key.isAcceptable()) {
SocketChannel client = serverSocket.accept();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
}
if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
client.read(buffer);
byte[] array = new byte[buffer.position()];
buffer.flip();
buffer.get(array);
System.out.println(new String(array));
buffer.clear();
}
iter.remove();
}
}
}
}
Nio client: send message. When client exist normaly or force closed by ctrl+c, the nio server will not be affected.
public class Client {
public static void main(String[] args) throws IOException, InterruptedException {
SocketChannel client = SocketChannel.open(new InetSocketAddress("localhost", 5454));
ByteBuffer buffer = ByteBuffer.wrap("hello world".getBytes());
client.write(buffer);
buffer.clear();
Thread.sleep(5000);
ByteBuffer buffer1 = ByteBuffer.wrap("hello world1".getBytes());
client.write(buffer1);
client.close();
}
}