Javaでインターネット接続が存在するかどうかを確認する方法は?
-
05-07-2019 - |
質問
Java経由でインターネットに接続できるかどうかをどのように確認しますか? 1つの方法は次のとおりです。
final URL url = new URL("http://www.google.com");
final URLConnection conn = url.openConnection();
... if we got here, we should have net ...
しかし、連続チェックを非常に頻繁に行う必要があり、インターネット接続が失われる可能性が非常に高い場合、特に、そのタスクを実行するのにより適切なものがありますか?
解決
実際のアプリケーションが必要とする場所に接続する必要があります。それ以外の場合は、無関係な場所(この場合はGoogle)への接続があるかどうかをテストしています。
特に、Webサービスと通信しようとしている場合、およびWebサービスを制御している場合は、何らかの安価な「ステータスを取得」することをお勧めします。 Webメソッド。そうすれば、「本物」かどうかをよりよく把握できます。呼び出しが動作する可能性があります。
他の場合、開いているはずのポートへの接続を開くだけで十分な場合があります-またはpingを送信します。 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メッセージをブロックするようにファイアウォールを構成していることです。したがって、「ping」はWebサービスにアクセスできる場合でも失敗する可能性があります。
そしてもちろん、その逆も同様です。 Webサーバーがダウンしている場合でも、ホストはpingに応答する場合があります。
そしてもちろん、ローカルファイアウォールの制限により、マシンが特定の(またはすべての)Webサーバーに直接接続できない場合があります。
根本的な問題は、「インターネットに接続できる」ことです。明確に定義されていない質問であり、この種のものはテストなしでは困難です:
- ユーザーのマシンと「ローカル」に関する情報。ネットワーク環境、および
- アプリがアクセスする必要があるものに関する情報。
一般的に、最も簡単な解決策は、アプリがアクセスする必要があるものにアクセスしようとし、診断を行うために人間の知能に頼ることです。
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());
Returns-to me-オフラインの場合は true
、そうでない場合は false
。 (まあ、これがすべてのコンピューターに当てはまるかどうかはわかりません)。
これは、ここまでの他のアプローチよりもはるかに高速に動作します。
編集:&quot;フリップスイッチ&quot; (ラップトップ)、またはインターネット接続用の他のシステム定義オプションがオフになっています。つまり、システム自体は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;
}
}
}
通常、3つのステップに分けます。
- まず、ドメイン名を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;
}
}
}
これは、IPv4ネットワークのopenSuse 13.1のJava 7で機能します。元のコードの問題は、サスペンドから再開した後にインターフェイスが起動したにもかかわらず、IPv4ネットワークアドレスがまだ割り当てられていないことです。この割り当てを待った後、プログラムはサーバーに接続できます。しかし、IPv6の場合はどうすればよいかわかりません。
InetAddress.isReachable
はいつかfalseを返します。
Javaでインターネットの可用性を確認する別の方法は次のとおりです。この関数は実際の 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;
}
}
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");
}
}
}