次のシナリオがあります。
- サーバーは ServerSocketChannel を開き、クライアント接続を受け入れます。
- すべての接続 (socketA) は新しいスレッドで処理されます。
- スレッド内で、別のサーバーに接続する新しい SocketChannel (socketB) を開きます。
- この時点で、元のクライアント接続 (socketA) はアイドル状態です。
- 新しい SocketChannel は、サーバーからデータを読み取ります (ブロック)。
今、私はスレッドを中断します。私は、socketB が中断されて閉じられ、socketA が引き続き機能することを期待していました。残念ながら、socketA も中断されます。
何が問題なのですか?
動作を再現するために、次のテスト方法を使用します。
private void testServerSocket() throws IOException, InterruptedException
{
final InetSocketAddress address = new InetSocketAddress( "localhost", 12345 );
final ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.socket().bind( address );
final SocketChannel socketChannel = serverChannel.accept();
// start communication in new thread
final Thread thread = new Thread( new Runnable() { @Override public void run() { testWrite( socketChannel ); } } );
thread.start();
// wait a little bit
Thread.sleep( 5000 );
// interrupt thread, will interrupt the socketChannel.read in testRead()
thread.interrupt();
thread.join();
socketChannel.close();
serverChannel.close();
}
void testWrite( SocketChannel socketA )
{
try
{
// write to client
socketA.write( ByteBuffer.wrap( "0123456789".getBytes() ) );
// open new socket to another server
testRead();
// throws ClosedByInterruptException
socketA.write( ByteBuffer.wrap( "0123456789".getBytes() ) );
}
catch( final IOException e )
{
e.printStackTrace();
}
}
void testRead()
{
try
{
final InetSocketAddress address = new InetSocketAddress( "localhost", 12346 );
final SocketChannel socketB = SocketChannel.open( address );
// server doesn't send, so this call will block and interrupted
socketB.read( ByteBuffer.wrap( new byte[10] ) );
socketB.close();
}
catch( final IOException e )
{
e.printStackTrace();
}
}