Java NIO非阻塞读取返回超时(linux内核问题?)

时间:2012-07-18 09:31:33

标签: java linux kernel nio nonblocking

我遇到了类似问题:Java Linux Nonblocking Socket Timeout Behavior

我有一个用Java NIO实现的应用程序。它跟踪一堆套接字,当它们准备好读取时,我的应用程序将循环读取(删除代码和一些逻辑以简洁):

        if (selkey.isReadable()) {
            int nread;
            while (true) {
                // read the header
                nread = mSocketChannel.read(mHeaderBuffer);
                if (nread == -1)
                    return;
                handle_message_header();
                // read the body
                nread = mSocketChannel.read(mPayloadBuffer);
                if (nread == -1)
                    return;
                handle_message_body();
            }
        }

但是很少,我很少在第一次读取()中收到超时异常:

    java.io.IOException: Connection timed out
    at sun.nio.ch.FileDispatcher.read0(Native Method)
    at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:21)
    at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:202)
    at sun.nio.ch.IOUtil.read(IOUtil.java:175)
    at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:243)

我深入研究了jdk源代码,read0函数只是调用socket句柄上的read()。如果read()返回-1并且errno == ETIMEDOUT,则抛出“连接超时”异常。

我们不使用soSetTimeout()或tcp keepalive选项。因为我只在客户端的集群上看到这个,所以我无法重现它(我也没有netstat或其他工具的输出)。

我想知道linux内核在非阻塞read()中返回ETIMEDOUT的情况是什么?这是一个错误还是一个功能?

有关出现这种情况的机器的更多信息:

Linux slave1 2.6.18-164.e15 #1 SMP Thu Sep 3 03:28:30 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
CentOS 5.4

由于 克里斯

编辑: 根据我的日志文件(和程序流程),当服务器接受传入连接时创建套接字。然后从该套接字中至少有一个成功的recv,但是服务器的两次失败了。然后我在阅读时发现了异常。 日志文件没有太多信息 - 因此我对目前的分析并不是100%肯定。我已经为套接字例程添加了大量的调试输出,现在我为下一次做好了准备。

感谢所有有用的评论!

2 个答案:

答案 0 :(得分:2)

您正在阅读尚未正确完成的连接。可能你在非阻塞模式下进行了连接,你或者没有收到OP_CONNECT事件;你还没有打电话给finishConnect();或者它没有返回true

答案 1 :(得分:0)

您的客户尝试连接但未收到任何回复,最终超时。

EJP,谢谢你的纠正。