単純な nio ベースの Java サーバーがあるとします。例(簡略化されたコード):
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();
}
}
}
したがって、これは単純なシングル スレッドのノンブロッキング サーバーです。
問題は次のコードにあります。
channel.read(buffer);
channel.close();
同じスレッド(接続と読み取りデータを受け入れるスレッド)でチャネルを閉じると、すべて正常に動作します。しかし、別のスレッドで接続が閉じられたときに問題が発生しました。例えば
((SocketChannel) channel).read(buffer);
executor.execute(new Runnable() {
public void run() {
channel.close();
}
});
このシナリオでは、ソケットがサーバーで TIME_WAIT 状態、クライアントで ESTABLISHED 状態になりました。そのため、接続が正常に閉じられません。何が問題なのですか?私が逃したものは何ですか?