这是一个跟进:
基本上,我有一个服务器循环来管理与一个单独客户端的连接.在循环中的某一点,如果ClientSocket存在,它会尝试读取以检查客户端是否仍然连接:
if (bufferedReader.read()==-1 ) {
logger.info("CONNECTION TERMINATED!");
clientSocket.close();
setUpSocket(); //sets up the server to reconnect to the client
}else{
sendHeartBeat(); //Send a heartbeat to the client
}
Run Code Online (Sandbox Code Playgroud)
问题是,一旦创建了套接字,应用程序将挂起读取,我假设等待永远不会发生的数据,因为客户端永远不会发送到服务器.在此之前没问题,因为正确处理断开连接(当客户端断开连接时读取最终会失败)并且循环将尝试重新建立连接.但是,我现在已经添加了上面的sendHeartBeat()方法,它定期让客户端知道服务器仍在运行.如果读取持有线程,则心跳永远不会发生!
所以,我假设我正在测试连接是否仍然不正确.我可以,作为一个快速的黑客,在一个单独的线程中运行bufferedReader.read(),但随后我将有各种各样的并发问题,我真的不想处理.
所以问题有几个:1)我是否正确检查客户端断开连接?2)如果没有,我该怎么办?3)如果我正确地这样做我怎么做我读取不让流程人质?或者是穿线唯一的方式?
创建套接字时,首先设置超时:
private int timeout = 10000;
private int maxTimeout = 25000;
clientSocket.setSoTimeout(timeout);
Run Code Online (Sandbox Code Playgroud)
有了这个,如果读取超时你将得到java.net.SocketTimeoutException(你必须抓住).因此,您可以执行类似这样的操作,假设您之前已经设置了SO_TIMEOUT,如上所示,并假设心跳将始终从远程系统获得响应:
volatile long lastReadTime;
try {
bufferedReader.read();
lastReadTime = System.currentTimeMillis();
} catch (SocketTimeoutException e) {
if (!isConnectionAlive()) {
logger.info("CONNECTION TERMINATED!");
clientSocket.close();
setUpSocket(); //sets up the server to reconnect to the client
} else {
sendHeartBeat(); //Send a heartbeat to the client
}
}
public boolean isConnectionAlive() {
return System.currentTimeMillis() - lastReadTime < maxTimeout;
}
Run Code Online (Sandbox Code Playgroud)
处理此问题的常用方法是将超时设置为某个数字(例如10秒),然后跟踪上次从套接字成功读取的时间.如果已超过2.5倍的超时,则放弃客户端并关闭套接字(因此发送FIN数据包到另一方,以防万一).
如果心跳不会从远程系统获得任何响应,但只是在连接断开时最终生成IOException的一种方法,那么你可以这样做(假设sendHeartBeat本身不会抛出IOException):
try {
if (bufferedReader.read() == -1) {
logger.info("CONNECTION TERMINATED with EOF!");
resetConnection();
}
} catch (SocketTimeoutException e) {
// This just means our read timed out ... the socket is still good
sendHeartBeat(); //Send a heartbeat to the client
} catch (IOException e) {
logger.info("CONNECTION TERMINATED with Exception " + e.getMessage());
resetConnection();
}
....
private void resetConnection() {
clientSocket.close();
setUpSocket(); //sets up the server to reconnect to the client
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
26754 次 |
| 最近记录: |