Domanda

Come si controlla se è possibile connettersi a Internet tramite Java? Un modo sarebbe:

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

Ma c'è qualcosa di più appropriato per eseguire tale compito, specialmente se è necessario eseguire controlli consecutivi molto spesso e una perdita di connessione a Internet è altamente probabile?

È stato utile?

Soluzione

Dovresti connetterti al luogo di cui ha bisogno l'applicazione reale. Altrimenti stai verificando se hai una connessione in qualche luogo irrilevante (Google in questo caso).

In particolare, se stai cercando di parlare con un servizio web e se hai il controllo del servizio web, sarebbe una buona idea avere una sorta di "economico" ottenere lo stato " metodo web. In questo modo hai un'idea molto migliore se il tuo "reale" è probabile che la chiamata funzioni.

In altri casi, basta aprire una connessione a una porta che dovrebbe essere aperta o inviare un ping. InetAddress.isReachable potrebbe essere un'API appropriata per le tue esigenze qui.

Altri suggerimenti

Il codice che hai sostanzialmente fornito, più una chiamata a connetti dovrebbe essere sufficiente. Quindi sì, potrebbe essere che solo Google non sia disponibile ma qualche altro sito che devi contattare è attivo, ma quanto è probabile? Inoltre, questo codice dovrebbe essere eseguito solo quando in realtà non riesci ad accedere alla tua risorsa esterna (in un blocco catch per cercare di capire quale fosse la causa dell'errore), quindi direi che se entrambi i tuoi risorsa di interesse esterna e Google non sono disponibili possibilità se hai un problema di connettività di rete.

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

Le persone hanno suggerito di utilizzare INetAddress.isReachable. Il problema è che alcuni siti configurano i propri firewall per bloccare i messaggi Ping ICMP. Quindi un " ping " potrebbe non riuscire anche se il servizio Web è accessibile.

E ovviamente anche il contrario è vero. Un host può rispondere a un ping anche se il server web è inattivo.

E, naturalmente, una macchina potrebbe non essere in grado di connettersi direttamente a determinati (o tutti) server Web a causa delle restrizioni del firewall locale.

Il problema fondamentale è che " può connettersi a Internet " è una domanda mal definita e questo genere di cose è difficile da testare senza:

  1. informazioni sulla macchina dell'utente e " local " ambiente di rete e
  2. informazioni su ciò a cui l'app deve accedere.

Quindi, generalmente, la soluzione più semplice è che un'app cerchi di accedere a tutto ciò di cui ha bisogno per accedere e ricorrere all'intelligenza umana per fare la diagnosi.

Se sei su Java 6 puoi usare NetworkInterface per verificare le interfacce di rete disponibili. Cioè qualcosa del genere:

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

Non l'ho ancora provato da solo.

Questo codice:

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

Restituisce - per me - true se offline, e false , altrimenti. (beh, non so se questo sia vero per tutti i computer).

Funziona molto più velocemente degli altri approcci, quassù.


EDIT: l'ho trovato funzionante solo se l'interruttore "flip" " (su un laptop), o qualche altra opzione definita dal sistema, per la connessione a Internet, è disattivata. Cioè, il sistema stesso non sa cercare alcun indirizzo IP.

Questo codice dovrebbe svolgere il lavoro in modo affidabile.

Nota che quando si utilizza try-with-resources non è necessario chiudere le risorse.

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

Di solito lo scompongo in tre passaggi.

  1. Per prima cosa vedo se riesco a risolvere il nome di dominio in un indirizzo IP.
  2. Provo quindi a connettermi via TCP (porta 80 e / o 443) e chiudere con grazia.
  3. Infine, invierò una richiesta HTTP e verificherò la risposta 200.

Se fallisce in qualsiasi momento, fornisco all'utente il messaggio di errore appropriato.

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();

Metti le istruzioni precedenti in try catch blocks e se un'eccezione in catch significa che non è stata stabilita alcuna connessione a Internet. : -)

Il codice che utilizza NetworkInterface per attendere che la rete funzionasse per me fino al passaggio da indirizzo di rete fisso a DHCP. Un leggero miglioramento lo fa funzionare anche con 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;
            }
    }
}

Funziona con Java 7 in openSuse 13.1 per la rete IPv4. Il problema con il codice originale è che sebbene l'interfaccia fosse attiva dopo la ripresa dalla sospensione, non è stato ancora assegnato un indirizzo di rete IPv4. Dopo aver atteso questo compito, il programma può connettersi ai server. Ma non ho idea di cosa fare in caso di IPv6.

InetAddress.isReachable a volte restituisce false se esiste una connessione Internet.

Un metodo alternativo per verificare la disponibilità di Internet in Java è: Questa funzione crea un vero ping 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) Scopri dove deve essere connessa la tua applicazione.

2) Imposta un processo di lavoro per controllare InetAddress.isReachable per monitorare la connessione a quell'indirizzo.

Questo codice è contenuto in una classe di test jUnit che utilizzo per verificare se è disponibile una connessione. Ricevo sempre una connessione, ma se controlli la lunghezza del contenuto dovrebbe essere -1 se non noto:

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

C'è anche un'opzione gradle --offline che forse porta al comportamento desiderato.

Il seguente codice ci consente di ottenere lo stato della rete sul nostro dispositivo 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");
            }
        }
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top