Как проверить, есть ли интернет-соединение в Java?

StackOverflow https://stackoverflow.com/questions/1402005

  •  05-07-2019
  •  | 
  •  

Вопрос

Как проверить, можно ли подключиться к Интернету через Java? Один из способов будет:

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

Но есть ли что-то более подходящее для выполнения этой задачи, особенно , если вам нужно выполнять последовательные проверки очень часто и вероятность подключения к Интернету высока?

Это было полезно?

Решение

Вы должны подключиться к месту, в котором нуждается ваше реальное приложение. В противном случае вы проверяете, есть ли у вас связь с чем-то несущественным (в данном случае Google).

В частности, если вы пытаетесь поговорить с веб-службой и если вы контролируете веб-службу, было бы неплохо иметь какой-то дешевый " получить статус " веб-метод. Таким образом, у вас будет гораздо лучшее представление о том, является ли ваш "реальным" звонок скорее всего сработает.

В других случаях достаточно просто открыть соединение с портом, который должен быть открыт, или отправить пинг. InetAddress.isReachable вполне может быть подходящим API для ваших нужд здесь.

Другие советы

Код, который вы в основном предоставили, плюс вызов connect должен быть достаточным. Так что да, может быть, просто Google не доступен, но есть другой сайт, с которым вам нужно связаться, но насколько вероятно это? Кроме того, этот код должен выполняться только тогда, когда вы фактически не можете получить доступ к своему внешнему ресурсу (в блоке 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;
    }
}

Люди предложили использовать INetAddress.isReachable. Проблема в том, что некоторые сайты настраивают свои брандмауэры для блокировки сообщений ICMP Ping. Так что "пинг" может произойти сбой, даже если веб-сервис доступен.

И, конечно, верно и обратное. Хост может ответить на эхо-запрос, даже если веб-сервер не работает.

И, конечно, машина может быть не в состоянии подключиться напрямую к определенным (или всем) веб-серверам из-за локальных ограничений брандмауэра.

Основная проблема заключается в том, что "можно подключиться к Интернету" является плохо определенным вопросом, без которого трудно проверить такие вещи:

<Ол>
  • информация о компьютере пользователя и "локальный" сетевая среда и
  • информация о том, что требуется приложению для доступа.
  • В общем, самое простое решение для приложения - просто попытаться получить доступ ко всему, что ему нужно, и прибегнуть к человеческому интеллекту для постановки диагноза.

    Если вы работаете в java 6, вы можете использовать NetworkInterface проверить наличие доступных сетевых интерфейсов. То есть как то так:

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

    Сам пока не пробовал.

    Этот код:

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

    Возвращает - мне - true в автономном режиме и false в противном случае. (ну, я не знаю, правда ли это для всех компьютеров).

    Это работает намного быстрее, чем другие подходы, здесь.

    <Ч>

    РЕДАКТИРОВАТЬ: я обнаружил, что это работает только в том случае, если переключатель <" (на ноутбуке) или какой-либо другой системный параметр для подключения к Интернету отключен. То есть сама система знает, что не нужно искать никаких IP-адресов.

    Этот код должен выполнять работу надежно.

    Обратите внимание, что при использовании 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;
            }
        }
    }
    

    Обычно я разбиваю его на три этапа.

    <Ол>
  • Сначала я вижу, могу ли я разрешить имя домена в IP-адрес.
  • Затем я пытаюсь подключиться через TCP (порт 80 и / или 443) и корректно закрыть.
  • Наконец, я отправлю HTTP-запрос и проверю ответ 200.
  • Если в любой момент происходит сбой, я предоставляю соответствующее сообщение об ошибке пользователю.

    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 означает, что подключение к Интернету не установлено. : -)

    Код, использующий 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;
                }
        }
    }
    

    Это работает для Java 7 в openSuse 13.1 для сети IPv4. Проблема с исходным кодом заключается в том, что, хотя интерфейс был отключен после возобновления из режима ожидания, сетевой адрес IPv4 еще не был назначен. После ожидания этого назначения программа может подключаться к серверам. Но я понятия не имею, что делать в случае IPv6.

    InetAddress.isReachable иногда возвращает false, если интернет-соединение существует.

    Альтернативный метод проверки доступности интернета в java: эта функция делает реальный пинг ICMP ECHO .

    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;
            }
    }
    

    1) Выясните, где ваше приложение должно подключаться.

    2) Настройте рабочий процесс для проверки InetAddress.isReachable для отслеживания соединения с этим адресом.

    Этот код содержится в тестовом классе 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();
      }
    
    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;
    }
    

    Существует также опция Gradle - offline , которая может привести к желаемому поведению.

    Следующий фрагмент кода позволяет нам получить статус сети на нашем устройстве Android

    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");
                }
            }
        }
    
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top