我遇到了类似问题: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%肯定。我已经为套接字例程添加了大量的调试输出,现在我为下一次做好了准备。
感谢所有有用的评论!
答案 0 :(得分:2)
您正在阅读尚未正确完成的连接。可能你在非阻塞模式下进行了连接,你或者没有收到OP_CONNECT
事件;你还没有打电话给finishConnect()
;或者它没有返回true
。
答案 1 :(得分:0)
您的客户尝试连接但未收到任何回复,最终超时。
EJP,谢谢你的纠正。