我遇到了此处描述的类似问题: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/