Suppose I have simple nio based java server. For example (simplified code):
while (!self.isInterrupted()) {
if (selector.select() <= 0) {
continue;
}
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
SelectableChannel channel = key.channel();
if (key.isValid() && key.isAcceptable()) {
SocketChannel client = ((ServerSocketChannel) channel).accept();
if (client != null) {
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
}
} else if (key.isValid() && key.isReadable()) {
channel.read(buffer);
channel.close();
}
}
}
So, this is simple single threaded non blocking server.
Problem reside in following code.
channel.read(buffer);
channel.close();
When I closing channel in same thread (thread that accept connection and reading data) all works fine. But I got a problem when connection closed in another thread. For example
((SocketChannel) channel).read(buffer);
executor.execute(new Runnable() {
public void run() {
channel.close();
}
});
In this scenario I ended up with socket in state TIME_WAIT on server and ESTABLISHED on client. So connection is not closing gracefully. Any ideas what's wrong? What I missed?
TIME_WAIT means the OS has received a request to close the socket, but waits for possible late communications from the client side. Client apparently didn't get the RST, since it's still thinks it's ESTABLISHED. It's not Java stuff, it's OS. RST is apparently delayed by OS -- for whatever reason.
Why it only happens when you close it in another thread -- who knows? May be OS believes that closes in another thread should wait for original thread exit, or something. As I said, it's OS internal mechanics.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With