0

我遇到了与此处所述类似的问题: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% 确定的。我已经为套接字例程添加了很多调试输出,现在我为下一次做好了更好的准备。

感谢所有有用的评论!

4

2 回答 2

2

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

于 2012-07-18T10:34:59.020 回答
0

您的客户端尝试连接但未收到响应并最终超时。

EJP,感谢您的更正。

于 2012-07-18T09:39:34.287 回答