Java检测丢失的连接

当我使用例如腻子和我的连接丢失(或当我在Windows上手动ipconfig /release ),它直接响应,并通知我的连接丢失。

我想创build一个Java程序来监视我的Internet连接(对于一些可靠的服务器),logging我的Internet失败时的date/时间。

我尝试使用Socket.isConnected()方法,但只是永远返回“真”。 我怎样才能在Java中做到这一点?

那么,判断你的连接是否被中断的最好方法是尝试从套接字读/写。 如果操作失败,那么您有时会丢失连接。

所以,你需要做的就是尝试阅读一段时间,如果读取失败尝试重新连接。

读取失败时,您将遇到的重要事件是 – 连接丢失,连接了新的套接字 – 重新连接。

这样你可以跟踪时间和停机时间。

即使TCP / IP是“面向连接”的协议,通常没有数据通过空闲连接发送。 您可以打开一个套接字一年,IP堆栈不会传送一位数据。 为了注意到连接丢失,您必须在应用程序级别发送一些数据。(*)您可以通过从ADSL调制解调器上拔下电话线来尝试。 您的PC中的所有连接应该保持连接,除非应用程序具有某种应用程序级别的存活机制。

因此,注意丢失连接的唯一方法是打开某个服务器的TCP连接并从中读取一些数据。 也许最简单的方法可能是连接到某个FTP服务器,并偶尔读取一个小文件或目录列表。 我从来没有见过一个真正用于这种情况的通用服务器,FTP服务器的所有者可能不喜欢这样做的客户端。

(*)还有一种称为TCP keepalive的机制,但在许多操作系统中,您必须为所有应用程序激活它,如果您想要注意到连接丢失,使用它并不实际

为什么不使用java.net.InetAddress类的isReachable()方法?

这是如何工作的JVM实现特定的,但:

如果可以获得特权,典型的实现将使用ICMP ECHO REQUEST,否则将尝试在目标主机的端口7(Echo)上build立TCP连接。

如果你想持续打开一个连接,这样你就可以看到什么时候失败了,你可以自己连接到运行ECHO协议的服务器,而不是让isReachable()为你做,读写数据并等待它失败。

如果客户端正确断开连接,则read()将返回-1, readLine()返回null,对于其他任何X抛出的readXXX()抛出EOFException 。 检测丢失的TCP连接的唯一可靠的方法是写入它。 因此最终会抛出IOException '连接重置',但由于缓冲至less需要两次写入。

您可能想要尝试查看套接字超时间隔 。 短暂超时(我相信默认是'无限超时'),那么你可能会陷入exception或主机变得无法访问的东西。

好吧,所以我终于搞定了

 try { Socket s = new Socket("stackoverflow.com",80); DataOutputStream os = new DataOutputStream(s.getOutputStream()); DataInputStream is = new DataInputStream(s.getInputStream()); while (true) { os.writeBytes("GET /index.html HTTP/1.0\n\n"); is.available(); Thread.sleep(1000); } } catch (IOException e) { System.out.println("connection probably lost"); e.printStackTrace(); } 

不像我所希望的那样干净,但是如果我省略os.writeBytes(),则不能工作。

Socket.java类中的isConnected()方法有点误导。 它不会告诉你套接字当前是否连接到远程主机(就像它没有closures一样)。 相反,它会告诉您套接字是否曾经连接到远程主机 。 如果套接字能够连接到远程主机,则该方法返回true ,即使该套接字已closures。 要告诉套接字当前是否打开,您需要检查isConnected()返回trueisClosed()返回false 。 例如:

 boolean connected = socket.isConnected() && !socket.isClosed(); 

你可以每隔几秒钟就可以ping一台机器,这是相当准确的。 小心你不要DOS。

另一种方法是在远程机器上运行一个小型服务器,并保持连接。

它可能更简单的连接到雅虎/谷歌或像这样的地方。

  URL yahoo = new URL("http://www.yahoo.com/"); URLConnection yc = yahoo.openConnection(); int dataLen = yc.getContentLength() ; 

尼尔