简体   繁体   中英

SocketChannel: interrupt close all open channels

I have the following scenario:

  • A server open's a ServerSocketChannel and accept client connections.
  • Every connection (socketA) is handled in a new thread.
  • Inside the thread I open a new SocketChannel (socketB) which connects a another server.
  • The original client connection (socketA) is idle at this time.
  • The new SocketChannel reads data (blocking) from the server.

Now I interrupt the thread. I expected that socketB will be interrupted and closed and socketA will be continue to work. Unfortunately socketA will also be interrupted.

Any idea what could be the problem?

I use the following test methods to reproduce the behavior:

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();
    }
}

You need to clear the thread's interrupted state by calling Thread.interrupted() after the IOException in testRead() . Actually you should catch ClosedByInterruptException and do it there. Otherwise the condition persists and interrupts the write as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM