【问题标题】:How to check if internet connection is present in Java?如何检查Java中是否存在互联网连接?
【发布时间】:2010-11-26 23:37:13
【问题描述】:

如何检查是否可以通过 java 连接到 Internet?一种方法是:

final URL url = new URL("http://www.google.com");
final URLConnection conn = url.openConnection();
... if we got here, we should have net ...

但是是否有更适合执行该任务的方法,尤其是如果您需要经常进行连续检查并且很可能会断开互联网连接? p>

【问题讨论】:

  • 这个问题的答案与其他相同形式的问题相同。确定任何资源是否可用的唯一正确方法是在正常执行过程中尝试使用它,并在发生故障时应对故障。任何其他技术都是试图预测未来的一种或另一种形式。

标签: java networking connection


【解决方案1】:

您应该连接到您的实际应用程序需要的位置。否则,您正在测试您是否与某个不相关的地方(在本例中为 Google)建立了连接。

特别是,如果您尝试与 Web 服务通信,并且您可以控制该 Web 服务,那么最好使用某种廉价的“获取状态”Web 方法。这样一来,您就可以更好地了解您的“真实”通话是否可能奏效。

在其他情况下,只需打开与应该打开的端口的连接就足够了 - 或者发送 ping。 InetAddress.isReachable 很可能是适合您需求的 API。

【讨论】:

  • isReachable 的链接指向了错误的类。在java.sun.com/javase/6/docs/api/java/net/…
  • 如果您连接到要与之通信的资源但失败了怎么办。你怎么知道这是目标服务器的问题,而不是 bcs 没有互联网连接?所以“连接到您的实际应用程序需要的地方”并不是真正的解决方案,也不是可靠的检查
  • @Chris:这取决于您是否真的关心问题所在。我同意,如果(发生故障后)您还可以连接到其他地方,您可以获得更多诊断信息。但最重要的信息肯定是“我可以使用我正在尝试使用的资源吗?”
  • @Pacerier:有很多不同的事情可能会出错,诊断哪里出了问题是一件棘手的事情。如果您什么都没做,但您的 ISP 通往世界其他地方的管道已经中断了怎么办?然后你可能仍然有一个完全有效的路由器连接等 - 你甚至可以访问你的 ISP 的域 - 但无法访问其他站点。我所说的只是“我的互联网上线了吗?”作为一个问题没有意义,真的 - 不是精确的。 建议测试应该是什么?
  • @Pacerier:所以你会尝试几个正常运行的网站。您还想检查 DNS 解析是否正常工作 - 实际上是否可以解析 facebook.com。然后,Facebook 可能会因大部分用户而关闭(例如,一个国家的流量会流向一个有问题的数据中心),而网站却没有完全关闭......
【解决方案2】:

您基本上提供的代码,加上对connect 的调用就足够了。所以,是的,可能只是谷歌不可用,但您需要联系的其他网站正在运行,但这种可能性有多大?此外,此代码仅应在您实际无法访问外部资源时执行(在 catch 块中尝试找出失败的原因是什么),所以我会说,如果您感兴趣的外部资源 并且 Google 不可用 您可能遇到网络连接问题。

private static boolean netIsAvailable() {
    try {
        final URL url = new URL("http://www.google.com");
        final URLConnection conn = url.openConnection();
        conn.connect();
        conn.getInputStream().close();
        return true;
    } catch (MalformedURLException e) {
        throw new RuntimeException(e);
    } catch (IOException e) {
        return false;
    }
}

【讨论】:

  • 这可行,但需要一段时间才能返回false。有更快的解决方案吗? Cmd 在我尝试 ping 时立即告诉我找不到主机。
【解决方案3】:

人们建议使用 INetAddress.isReachable。问题是某些站点将其防火墙配置为阻止 ICMP Ping 消息。因此,即使可以访问 Web 服务,“ping”也可能会失败。

当然,反过来也是如此。即使网络服务器已关闭,主机也可能会响应 ping。

当然,由于本地防火墙限制,一台机器可能无法直接连接到某些(或所有)网络服务器。

根本问题是“能否连接到互联网”是一个定义不明确的问题,没有这种东西很难测试:

  1. 有关用户机器和“本地”网络环境的信息,以及
  2. 有关应用需要访问什么的信息。

因此,一般来说,最简单的解决方案是让应用尝试访问它需要访问的任何内容,然后依靠人类智能进行诊断。

【讨论】:

  • 好吧,不是定义不明确。问题只是“有互联网”而已。
  • 这是我的观点。 “是否有互联网”的问题定义不明确。阅读上面的文本,了解旨在说明这一点的示例。
  • @Chris:“互联网”定义不明确。例如,能够访问 Google 并不意味着您一定可以访问其他任何地方。 (想象一下,如果 DNS 服务器已关闭,但您的 hosts 文件中恰好有一个 DNS 条目。)
  • 无法访问 Google 并不意味着您无法到达用户真正想去的地方。
  • @Stephen C:好的,现在我明白了。也许我必须尝试另一种方式来满足我的需要。感谢 cmets。
【解决方案4】:

如果您使用的是 java 6,可以使用 NetworkInterface 检查可用的网络接口。 IE。像这样:

Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
  NetworkInterface interf = interfaces.nextElement();
  if (interf.isUp() && !interf.isLoopback())
    return true;
}

我自己还没试过。

【讨论】:

  • 这仅检查接口是否启用。它不检查互联网连接。
  • 不过,网络接口启动是互联网连接的先决条件。我认为这是一个更强大的解决方案的第一步。它至少允许您查看您是否有一个活动的网络接口,而根本不发送任何网络流量。
  • 这不是 OP 要求的。
  • OP 不明白“互联网是否上线”的问题定义不明确,因为互联网有很多东西,其中任何数量都可能上升或下降,从而导致广泛的各种类型的故障。这是其中之一,对于 OP 或检查此问题的其他人来说可能是有用的信息。 OP 拒绝简单地连接到所需的资源。除此之外,这是回答定义不明确的原始问题的众多步骤之一。
【解决方案5】:

这段代码应该可以可靠地完成这项工作。

请注意,当使用try-with-resources 语句时,我们不需要关闭资源。

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class InternetAvailabilityChecker
{
    public static boolean isInternetAvailable() throws IOException
    {
        return isHostAvailable("google.com") || isHostAvailable("amazon.com")
                || isHostAvailable("facebook.com")|| isHostAvailable("apple.com");
    }

    private static boolean isHostAvailable(String hostName) throws IOException
    {
        try(Socket socket = new Socket())
        {
            int port = 80;
            InetSocketAddress socketAddress = new InetSocketAddress(hostName, port);
            socket.connect(socketAddress, 3000);

            return true;
        }
        catch(UnknownHostException unknownHost)
        {
            return false;
        }
    }
}

【讨论】:

    【解决方案6】:

    这段代码:

    "127.0.0.1".equals(InetAddress.getLocalHost().getHostAddress().toString());
    

    如果离线,则返回 - 给我 - true,否则返回 false。 (好吧,我不知道这是否适用于所有计算机)。

    这比这里的其他方法工作得更快。


    编辑:我发现这只有在“翻转开关”(在笔记本电脑上)或其他系统定义的互联网连接选项关闭时才有效。也就是说,系统本身知道不查找任何 IP 地址。

    【讨论】:

    • 不适用于“127.0.0.1”,但显示对其他可访问 IP 地址的回复
    • 为我工作,我喜欢它并使用它。这是一种预先检查。初步检查以确保网络接口已连接,您可以在检查 Internet 连接之前调用它。
    【解决方案7】:

    我通常把它分解成三个步骤。

    1. 我先看看能不能把域名解析成IP地址。
    2. 然后我尝试通过 TCP(端口 80 和/或 443)连接并正常关闭。
    3. 最后,我将发出一个 HTTP 请求并检查返回的 200 响应。

    如果它在任何时候失败,我会向用户提供相应的错误消息。

    【讨论】:

    • 我认为这可能是一个很好的答案,但你能详细说明一下吗,因为它现在不是一个很好的答案。
    【解决方案8】:
    URL url=new URL("http://[any domain]");
    URLConnection con=url.openConnection();
    
    /*now errors WILL arise here, i hav tried myself and it always shows "connected" so we'll open an InputStream on the connection, this way we know for sure that we're connected to d internet */
    
    /* Get input stream */
    con.getInputStream();
    

    将上述语句放入 try catch 块中,如果 catch 中的异常意味着没有建立互联网连接。 :-)

    【讨论】:

      【解决方案9】:

      使用 NetworkInterface 等待网络的代码为我工作,直到我从固定网络地址切换到 DHCP。稍有改进后,它也可以与 DHCP 一起使用:

      Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
      while (interfaces.hasMoreElements()) {
          NetworkInterface interf = interfaces.nextElement();
          if (interf.isUp() && !interf.isLoopback()) {
          List<InterfaceAddress> adrs = interf.getInterfaceAddresses();
          for (Iterator<InterfaceAddress> iter = adrs.iterator(); iter.hasNext();) {
              InterfaceAddress adr = iter.next();
              InetAddress inadr = adr.getAddress();
              if (inadr instanceof Inet4Address) return true;
                  }
          }
      }
      

      这适用于用于 IPv4 网络的 openSuse 13.1 中的 Java 7。原始代码的问题在于,虽然从挂起恢复后接口已启动,但尚未分配 IPv4 网络地址。等待此分配后,程序可以连接到服务器。但我不知道在 IPv6 的情况下该怎么做。

      【讨论】:

        【解决方案10】:

        InetAddress.isReachable 如果存在互联网连接,有时会返回 false。

        在 java 中检查 Internet 可用性的另一种方法是:此函数生成真正的ICMP ECHO ping。

        public static boolean isReachableByPing(String host) {
             try{
                        String cmd = "";
                        if(System.getProperty("os.name").startsWith("Windows")) {   
                                // For Windows
                                cmd = "ping -n 1 " + host;
                        } else {
                                // For Linux and OSX
                                cmd = "ping -c 1 " + host;
                        }
        
                        Process myProcess = Runtime.getRuntime().exec(cmd);
                        myProcess.waitFor();
        
                        if(myProcess.exitValue() == 0) {
        
                                return true;
                        } else {
        
                                return false;
                        }
        
                } catch( Exception e ) {
        
                        e.printStackTrace();
                        return false;
                }
        }
        

        【讨论】:

          【解决方案11】:

          1) 找出您的应用程序需要连接到的位置。

          2) 设置一个工作进程来检查InetAddress.isReachable 以监控与该地址的连接。

          【讨论】:

            【解决方案12】:

            此代码包含在我用来测试连接是否可用的 jUnit 测试类中。我总是收到一个连接,但如果你检查内容长度,如果不知道它应该是 -1:

              try {
                URL url = new URL("http://www.google.com");
                URLConnection connection = url.openConnection();
            
                if(connection.getContentLength() == -1){
                      fail("Failed to verify connection");
                }
              } 
              catch (IOException e) {
                  fail("Failed to open a connection");
                  e.printStackTrace();
              }
            

            【讨论】:

              【解决方案13】:
              public boolean checkInternetConnection()
              {
                   boolean status = false;
                   Socket sock = new Socket();
                   InetSocketAddress address = new InetSocketAddress("www.google.com", 80);
              
                   try
                   {
                      sock.connect(address, 3000);
                      if(sock.isConnected()) status = true;
                   }
                   catch(Exception e)
                   {
                       status = false;       
                   }
                   finally
                   {
                      try
                       {
                          sock.close();
                       }
                       catch(Exception e){}
                   }
              
                   return status;
              }
              

              【讨论】:

                【解决方案14】:

                你可以这样写

                import java.net.InetAddress;
                import java.net.UnknownHostException;
                
                public class Main {
                
                    private static final String HOST = "localhost";
                
                    public static void main(String[] args) throws UnknownHostException {
                
                        boolean isConnected = !HOST.equals(InetAddress.getLocalHost().getHostAddress().toString());
                
                        if (isConnected) System.out.println("Connected");
                        else System.out.println("Not connected");
                
                    }
                }
                

                【讨论】:

                  【解决方案15】:

                  还有一个 gradle 选项 --offline 可能会导致您想要的行为。

                  【讨论】:

                  • 这似乎与问题无关。
                  【解决方案16】:

                  下面这段代码让我们可以在我们的安卓设备上获取网络的状态

                  public class MainActivity extends AppCompatActivity {
                          @Override
                          protected void onCreate(Bundle savedInstanceState) {
                              super.onCreate(savedInstanceState);
                              setContentView(R.layout.activity_main);
                              TextView mtv=findViewById(R.id.textv);
                              ConnectivityManager connectivityManager=
                                    (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
                              if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                  if(((Network)connectivityManager.getActiveNetwork())!=null)
                                      mtv.setText("true");
                                  else
                                      mtv.setText("fasle");
                              }
                          }
                      }
                  

                  【讨论】:

                  • 欢迎来到 StackOverflow。请始终包含文字说明。此外,您似乎只是从上下文中提取了一些代码,包括与问题无关的代码。您越是让其他人努力破译隐藏在您帖子中的信息,您对每个人的帮助就越少。这仅适用于 Android 吗?
                  猜你喜欢
                  • 1970-01-01
                  • 2019-09-03
                  • 1970-01-01
                  • 2015-05-25
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多