Java检测丢失的连接

Java检测丢失的连接,java,tcp,connection,Java,Tcp,Connection,当我使用PuTTY等工具时,我的连接丢失(或在Windows上执行手动ipconfig/release),它会直接响应并通知我的连接丢失 我想创建一个Java程序来监控我的互联网连接(到某个可靠的服务器),记录我的互联网出现故障的日期/时间 我尝试使用Socket.isConnected()方法,但这将永远返回“true”。如何在Java中做到这一点?好吧,判断连接是否中断的最好方法是尝试从套接字读/写。如果操作失败,则表示您有时已失去连接 因此,您所需要做的就是每隔一段时间尝试读取,如果读取失

当我使用PuTTY等工具时,我的连接丢失(或在Windows上执行手动
ipconfig/release
),它会直接响应并通知我的连接丢失

我想创建一个Java程序来监控我的互联网连接(到某个可靠的服务器),记录我的互联网出现故障的日期/时间


我尝试使用
Socket.isConnected()
方法,但这将永远返回“true”。如何在Java中做到这一点?

好吧,判断连接是否中断的最好方法是尝试从套接字读/写。如果操作失败,则表示您有时已失去连接

因此,您所需要做的就是每隔一段时间尝试读取,如果读取失败,请尝试重新连接

对于您来说,重要的事件是当读取失败时—您失去了连接,当连接了新套接字时—您重新获得了连接

这样,您就可以跟踪运行时间和停机时间。

为什么不使用
java.net.InetAddress
类的方法呢

其工作方式与JVM实现有关,但:

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


如果您想保持连接持续打开,以便在出现故障时查看,您可以自己连接到运行的服务器,而不是让
isReachable()
为您执行此操作并读取和写入数据,然后等待它失败。

您可以每隔几秒钟ping一次机器,这将非常准确。小心别这样做


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

连接到雅虎/谷歌或类似的地方可能更简单

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

尼尔

你可能想看看插座。如果超时时间很短(我相信默认值是“无限超时”),那么当主机无法访问时,您可能会捕获异常或其他情况。

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

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


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

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(),它就不起作用了。

如果客户端正确断开连接,
read()
将返回-1,
readLine()
返回null,
readXXX()
对于任何其他X抛出
EOFEException
。检测丢失的TCP连接的唯一可靠方法是对其进行写入。最终,这将抛出一个
IOException
“连接重置”,但由于缓冲,至少需要两次写入。

Socket.java类中的
isConnected()
方法有点误导。它不会告诉您套接字当前是否连接到远程主机(如未关闭)相反,它会告诉您套接字是否曾经连接到远程主机。如果套接字能够连接到远程主机,则此方法返回
true
,即使在关闭该套接字之后也是如此。要判断套接字当前是否打开,需要检查
isConnected()
是否返回
true
isClosed()
是否返回
false
。 例如:

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

嗯,也许我的问题不清楚。在我的系统中,有时会发生的情况是,我的互联网断开几秒钟,所有连接都被关闭。一秒钟后一切都好了。我想每天监测这一情况,报告这一情况发生的频率;将此添加到答案中。现有连接是否仍处于打开状态与
isReachable()
无关。这是您绝对不应该使用的。这几乎可以被认为是针对stackoverflow.com的DOS攻击!一种更友好的方法是在web主机上承载一个简单的页面/脚本,它(很可能)不会介意这样的恒定负载,特别是当呈现的页面很小时(只要一个简单的“h”就可以了)。这应该提供一个很小的脚印,如果每隔一秒钟左右进行一次调用,服务器可能不会陷入瘫痪,导致拒绝服务。不管怎么说,理论上讲,这是胡说八道。调用available()通常是毫无意义的,调用它并丢弃结果肯定是毫无意义的。睡眠简直是浪费时间。这项技术完全不起作用。它不能检测所有病例。你必须读或写一些东西到套接字。不正确。如果您设置了读取超时,并且它触发了一个异常,即操作失败,但不一定表示连接丢失。@EJP它并不总是正确的,但它会让您很好地了解发生了什么。不,它不会。您无法区分服务器速度慢和读取超时的连接丢失。与现有连接是否为st无关