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

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

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

    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 函数只是在套接字句柄上调用 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% 确定。我已将大量调试输出添加到套接字例程中,现在我为下一次做好了更好的准备。

感谢所有有用的评论!

最佳答案

您正在从尚未正确完成的连接中读取数据。可能您在非阻塞模式下进行了连接,并且您没有收到 OP_CONNECT 事件;你还没有调用 finishConnect();或者它没有返回 true

关于Java NIO 非阻塞读取返回超时(linux 内核问题?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11538329/

相关文章:

linux - 无法将字符串转换为 bool 值 - 可以在 Linux 上转换为 powershell

c++ - 在对内核代码进行字符串化后更改 openCL C++ 的主机端代码

java - ImageJ JavaScript,如何循环浏览目录?

java - 在命令行 java 中突出显示文本

java - 如何在非 ICS android 设备上拥有 android ICS 组件

linux - 如何从 vmlinux 安装 debuginfo 包

windows - VS 2012 中 'Debugger Immediate Window' 中的 KdPrintEx 不打印任何消息

调用 glDrawElements() 时发生 Java fatal error

android - Ubuntu - 如何将整个 Android 项目提交到本地存储库?

linux - 如何知道 tar 命令何时完成?