【问题标题】:SocketChannel: interrupt close all open channelsSocketChannel:中断关闭所有打开的通道
【发布时间】:2012-12-17 09:59:38
【问题描述】:

我有以下场景:

  • 服务器打开一个 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();
    }
}

【问题讨论】:

    标签: java socketchannel


    【解决方案1】:

    您需要通过在testRead() 中的IOException 之后调用Thread.interrupted() 来清除线程的中断状态。实际上你应该抓住ClosedByInterruptException 并在那里做。否则,该条件仍然存在并中断写入。

    【讨论】:

    • 但这不可能是解决问题的通用方法。如果我将 testRead 中的 SocketChannel 代码替换为简单的 Thread.sleep(20000),socketA 将不会被中断。
    • 而在现实生活中,我没有简单的 testRead 和 testWrite 函数。例如,在我的服务器中,testRead 函数不是来自我,而是来自 java 运行时的 CORBA 函数。
    • @user1909432 真正的解决方案是不中断线程,而是关闭套接字并让线程在这种情况下自行退出。
    • 我应该怎么做?示例中的 testRead 方法是现实生活中的 CORBA 调用,它可以挂起几分钟而不会超时。我应该如何实现没有中断的超时处理?据我所知,SocketChannel 正是出于这个原因实现了 InterruptibleChannel 接口。
    猜你喜欢
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 2012-02-17
    • 1970-01-01
    • 2021-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多