如何识别计算机唤醒后在MacOSX上损坏的Java套接字连接

如何识别计算机唤醒后在MacOSX上损坏的Java套接字连接

问题描述:

我有一个Java客户端应该不断连接​​到某个Java服务器,并输出任何服务器发送的内容(请参阅下面的摘录)。如何识别计算机唤醒后在MacOSX上损坏的Java套接字连接

问题是,如果客户端计算机(MacOS X)进入休眠状态,然后再次唤醒,客户端挂起在in.readLine(),并没有意识到连接中断。我向套接字添加了一个SO_TIMEOUT,以便客户端在readLine()上停止阻塞,并且确实抛出了SocketTimeoutException,但是然后愉快地尝试再次从断开的连接中读取一行。

我的问题是:为什么不in.readLine()失败,并IOException(这样我就可以重新启动连接),我怎样才能使客户端重新连接到服务器上的awake->sleep->awake周期在Mac OS X?

Socket socket = new Socket(...); 
socket.setSoTimeout(10000); 
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
[...] 
while (true) { 
    try { 
     while ((serverSays = in.readLine()) != null) { 
      System.out.println("Server says: " + serverSays); 
     } 
    } catch (SocketTimeoutException e) { 
     continue; 
    } 
    // An exception other than SocketTimeoutException will break the while-loop. 
} 
// If another exception other than SocketTimeoutException occurs, 
// catch it and re-initiate the connection and start over. 

IOException意味着本地主机知道远程主机不再提供数据。

SocketTimeoutException意味着远程主机根本无法在分配的时间内提供数据。它从未告诉我们该连接正式停止。

SocketTimeoutException当连接没有正常关闭时发生。如果远程主机电源中断,或者有人将以太网电缆从中拔出,那就是您所得到的。

在这种情况下,当您睡觉时,远程主机必须决定关闭连接,但您的主机错过了正在睡觉的通知。

解决的办法是假定连接在超过一定数量的超时后死亡。

如果您需要使用超时和重新连接,如果插座坏了,试试这个:

Socket socket = new Socket(...); 
socket.setSoTimeout(10000); 
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
[...] 
while (true) { 
    try { 
     while ((serverSays = in.readLine()) != null) { 
      System.out.println("Server says: " + serverSays); 
     } 
    } catch (SocketTimeoutException e) { 
     continue; 
    } catch (IOException e) { 
     //reconnecting with new Socket object and new reader, because old stream closed 
     socket = new Socket(...); 
     socket.setSoTimeout(10000); 
     in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
    } 
} 
+0

问题是'IOException'永远不会被抛出。它只是抛出'SocketTimeoutException',然后尝试再次读取一行,一遍又一遍。即使我杀死另一端的服务器,客户端仍会尝试读取一行(不抛出'IOException')。 –

+0

您可以尝试ping此连接。尝试发送简单的数据到服务器。如果成功,那么连接是活着的,否则关闭套接字并在我的第二个catch块中执行代码。 –

+0

你可以检查socket.isConnected(),但我不确定它是否有帮助。 –