簡體   English   中英

SocketChannel:中斷關閉所有打開的通道

[英]SocketChannel: interrupt close all open channels

我有以下情況:

  • 服務器打開一個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();
    }
}

您需要通過在testRead()IOException之后調用Thread.interrupted()來清除線程的中斷狀態。 實際上,您應該捕獲ClosedByInterruptException並在那里執行。 否則,條件仍然存在,並且也會中斷寫入。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM