我有一个 TCP 服务器和客户端,它们都是用 Java 编写的,并且在带有 jdk1.6 的 Rhel 5.3 上的不同机器上运行。我已经处理了几乎所有我能找到的检测“服务器”断开连接的方法。
以下是服务器代码的片段
private void listenforConnection() {
try {
socket = serverSocket.accept();
socket.setTcpNoDelay(true);
socket.setKeepAlive(true);
socket.setSoTimeout(5);
bosTcpOutStream = new BufferedOutputStream(socket.getOutputStream());
bisTcpInStream = new BufferedInputStream(socket.getInputStream());
log("New connection accepted from " + socket.getRemoteSocketAddress().toString());
sendHeartBeatsToClient();
} catch (IOException ie) {
log("Listener IOException : " + ie.getMessage());
}
}
private void sendHeartBeatsToClient() {
try {
while (true) {
long lngCurrentMillis=System.currentTimeMillis() ;
if ((lngCurrentMillis - lngLastSentMessageTime) >= 5000) {
byte[] bHeartBeat = getHeartBeatMessage();
bosTcpOutStream.write(bHeartBeat);
bosTcpOutStream.flush();
lngLastSentMessageTime = System.currentTimeMillis();
log("Heartbeat sent.");
} else {
try {
if (bisTcpInStream.read() == -1) {
log("Read Input Stream returned -1");
break;
}
} catch (SocketTimeoutException se) {
//Do nothing as i am not expecting the client to send anything.
} catch (IOException e) {
log("Read Input Stream error - " + e.getMessage());
break;
}
}
Thread.sleep(1);
}
} catch (IOException e) {
disconnectClientAndCloseSocket();
log("IO Exception" +e.getMessage());
} catch (InterruptedException e) {
disconnectClientAndCloseSocket();
log("Thread interrupted terminating." + e.getMessage());
}
}
我还修改了“服务器”机器上的 tcp-keepalive 内核参数,如下所示:
net.ipv4.tcp_keepalive_time=2
net.ipv4.tcp_keepalive_probes=1
net.ipv4.tcp_keepalive_intvl=2
现在,当我通过拔下客户端计算机的网络电缆来模拟断开连接时(在它建立连接并从服务器接收到初始数据之后),我看到了两种我无法理解的不同结果:-
如果我在成功连接客户端 10 到 15 秒后拔下电缆。在拔下电缆10 分钟后,在“服务器”上,我收到“无主机路由”的 IO 异常。
如果我在客户端连接成功 60 秒左右后拔下电缆。在“服务器”上,会在 10 秒内引发 IO 异常,并显示“连接超时” 。这是有效的行为,请记住保持活动设置。
我已经尝试了几次,我总是得到相同的结果。
我不明白为什么第一个结果需要 10 分钟,而且它的行为不像第二个结果。我错过了什么吗?