首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JDK1.7阻塞网络NIO过程中的IOException

JDK1.7阻塞网络NIO过程中的IOException
EN

Stack Overflow用户
提问于 2013-10-21 15:51:56
回答 1查看 1.4K关注 0票数 0

我只是在学习NIO,下面是我编写的测试阻塞NIO如何被中断的简短示例:

代码语言:javascript
复制
class TestBlockingNio {
    private static final boolean INTERRUPT_VIA_THREAD_INTERRUPT = true;

    /**
     * Prevent the socket from being GC'ed
     */
    static Socket socket;

    private static SocketChannel connect(final int port) {
        while (true) {
            try {
                final SocketChannel channel = SocketChannel.open(new InetSocketAddress(port));
                channel.configureBlocking(true);
                return channel;
            } catch (final IOException ioe) {
                try {
                    Thread.sleep(1000);
                } catch (final InterruptedException ie) {
                }
                continue;
            }
        }
    }

    private static byte[] newBuffer(final int length) {
        final byte buffer[] = new byte[length];
        for (int i = 0; i < length; i++) {
            buffer[i] = (byte) 'A';
        }
        return buffer;
    }

    public static void main(final String args[]) throws IOException, InterruptedException {
        final int portNumber = 10000;

        new Thread("Reader") {
            public void run() {
                try {
                    final ServerSocket serverSocket = new ServerSocket(portNumber);
                    socket = serverSocket.accept();
                    /*
                     * Fully ignore any input from the socket
                     */
                } catch (final IOException ioe) {
                    ioe.printStackTrace();
                }
            }

        }.start();

        final SocketChannel channel = connect(portNumber);

        final Thread main = Thread.currentThread();
        final Thread interruptor = new Thread("Inerruptor") {
            public void run() {
                System.out.println("Press Enter to interrupt I/O ");
                while (true) {
                    try {
                        System.in.read();
                    } catch (final IOException ioe) {
                        ioe.printStackTrace();
                    }
                    System.out.println("Interrupting...");
                    if (INTERRUPT_VIA_THREAD_INTERRUPT) {
                        main.interrupt();
                    } else {
                        try {
                            channel.close();
                        } catch (final IOException ioe) {
                            System.out.println(ioe.getMessage());
                        }
                    }
                }
            }
        };
        interruptor.setDaemon(true);
        interruptor.start();

        final ByteBuffer buffer = ByteBuffer.allocate(32768);    
        int i = 0;

        try {
            while (true) {
                buffer.clear();
                buffer.put(newBuffer(buffer.capacity()));
                buffer.flip();
                channel.write(buffer);
                System.out.print('X');
                if (++i % 80 == 0) {
                    System.out.println();
                    Thread.sleep(100);
                }
            }
        } catch (final ClosedByInterruptException cbie) {
            System.out.println("Closed via Thread.interrupt()");
        } catch (final AsynchronousCloseException ace) {
            System.out.println("Closed via Channel.close()");
        }
    }
}

在上面的例子中,我正在写入一个SocketChannel,但是没有人从另一边读取,所以写操作最终会挂起。

这个示例在JDK-1.6运行时工作得很好,输出如下:

代码语言:javascript
复制
    Press Enter to interrupt I/O 
    XXXX
    Interrupting...
    Closed via Thread.interrupt()

-意味着只有128 k的数据被写入TCP套接字的缓冲区。但是,当由JDK-1.7 (1.7.0_25-b15和1.7.0-u40-b37)运行时,相同的代码会出现在IOException中。

代码语言:javascript
复制
    Press Enter to interrupt I/O 
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    XXXXXXXXXXX
    Exception in thread "main" java.io.IOException: Broken pipe
        at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
        at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
        at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
        at sun.nio.ch.IOUtil.write(IOUtil.java:65)
        at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:487)
        at com.example.TestBlockingNio.main(TestBlockingNio.java:109)

有人能解释一下这种不同的行为吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-10-22 11:55:21

显然,在特定JVM版本如何将服务器套接字绑定到端口方面存在差异。

结果发现,我的第三方进程监听了127.0.0.1:10000,这在SocketChannel.open(new InetSocketAddress(10000))期间从未导致SocketChannel.open(new InetSocketAddress(10000))

同时,1.6VM正在使用en0成功地连接到自身,而1.7-VM则使用lo0连接到外部进程。一旦进程被终止,JVM行为在不同版本之间就会再次保持一致。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19499160

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档