IP 주소로 ping을 실행할 수 있는데 InetAddress.isReachable이 false를 반환하는 이유는 무엇입니까?
InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
?는 왜?isReachable
false
IP ping 을 사용합니다.
"isReachable" 메서드는 많은 경우 사용할 가치가 없습니다.아래까지 스크롤하면 온라인 상태이며 외부 호스트(google.com 등)를 해결할 수 있는지 간단하게 테스트할 수 있습니다.일반적으로는 *NIX 머신에서 동작하는 것 같습니다.
문제
이것에 대해서는, 많은 잡담이 있습니다.
다음은 기타 유사한 질문입니다.
또, 같은 문제에 관해서 보고된 버그도 있습니다.
파트 1 : 재현 가능한 문제의 예
이 경우 실패하는 것에 주의해 주세요.
//also, this fails for an invalid address, like "www.sjdosgoogle.com1234sd"
InetAddress[] addresses = InetAddress.getAllByName("www.google.com");
for (InetAddress address : addresses) {
if (address.isReachable(10000))
{
System.out.println("Connected "+ address);
}
else
{
System.out.println("Failed "+address);
}
}
//output:*Failed www.google.com/74.125.227.114*
파트 2: 해킹 회피책
다른 방법으로 다음과 같은 작업을 수행할 수 있습니다.
// in case of Linux change the 'n' to 'c'
Process p1 = java.lang.Runtime.getRuntime().exec("ping -n 1 www.google.com");
int returnVal = p1.waitFor();
boolean reachable = (returnVal==0);
ping의 -c 옵션을 사용하면 (단말기에서 사용하던 무한 ping과는 달리) 서버에 대한 ping을 한 번만 시도할 수 있습니다.
호스트에 연결할 수 있는 경우 0이 반환됩니다.그렇지 않으면 반환값으로 "2"가 표시됩니다.
훨씬 더 단순하지만 물론 플랫폼마다 다릅니다.또한 이 명령어를 사용할 때 특정 권한에 대한 경고가 있을 수 있지만, 제 컴퓨터에서는 이 명령어가 작동한다는 것을 알 수 있습니다.
주의: 1) 이 솔루션은 생산 품질이 아닙니다.좀 엉터리야.Google이 다운되거나 인터넷 속도가 일시적으로 느려지거나 권한/시스템 설정에 약간의 웃김이 있더라도 잘못된 음성이 반환될 수 있습니다(입력 주소가 도달 가능하더라도 실패할 수 있음).2) isReachable 장애는 해결되지 않은 문제입니다.다시 말씀드리지만, JVM이 호스트에 도달하는 방법 때문에 이 문서 작성 시 "완벽한" 방법이 없음을 나타내는 온라인 리소스가 몇 개 있습니다.이것은 본질적으로 플랫폼 고유의 작업이며, JVM에 의해 아직 충분히 추상화되지 않았습니다.
이 질문에 대한 답변을 얻으려고 왔습니다만, 플랫폼에 의존하지 않는 솔루션을 찾고 있었기 때문에 어떤 답변에도 만족하지 못했습니다.다음은 제가 작성한 코드입니다.플랫폼에 의존하지 않습니다만, 다른 머신의 오픈 포토에 관한 정보가 필요합니다(대부분의 경우).
private static boolean isReachable(String addr, int openPort, int timeOutMillis) {
// Any Open port on other machine
// openPort = 22 - ssh, 80 or 443 - webserver, 25 - mailserver etc.
try {
try (Socket soc = new Socket()) {
soc.connect(new InetSocketAddress(addr, openPort), timeOutMillis);
}
return true;
} catch (IOException ex) {
return false;
}
}
업데이트: 이 답변에 대한 최근 코멘트를 바탕으로 상기 코드의 간결한 버전을 소개합니다.
private static boolean isReachable(String addr, int openPort, int timeOutMillis) {
// Any Open port on other machine
// openPort = 22 - ssh, 80 or 443 - webserver, 25 - mailserver etc.
try (Socket soc = new Socket()) {
soc.connect(new InetSocketAddress(addr, openPort), timeOutMillis);
return true;
} catch (IOException ex) {
return false;
}
}
인터넷에 연결되어 있는지 여부만 확인하는 경우 인터넷이 연결되어 있으면 true, 프로그램을 통해 연결하려는 사이트의 주소를 사용하는 경우 true가 반환됩니다.
public static boolean isInternetReachable()
{
try {
//make a URL to a known source
URL url = new URL("http://www.google.com");
//open a connection to that source
HttpURLConnection urlConnect = (HttpURLConnection)url.openConnection();
//trying to retrieve data from the source. If there
//is no connection, this line will fail
Object objData = urlConnect.getContent();
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
다른 답변들은 그렇지 않으니 그냥 명시적으로 언급하는 겁니다.isReachable()의 ping 부분에는 Unix의 루트액세스가 필요합니다.4779367에서 지적한 바와 같이
그리고 bash에서 ping을 실행할 수 없는 이유를 묻는다면 실제로도 ping이 필요합니다.LS -l /bin/ping 을 실행합니다.
이 경우 root을 사용하는 것은 선택사항이 아니었기 때문에 방화벽 내의 포트7에 접속하여 관심 있는 특정 서버에 접속할 수 있도록 하는 것이 해결책이었습니다.
나는 2012년에 원래의 질문을 받았을 때 어떤 상태였는지 잘 모르겠다.
현재 상태에서는 ping이 루트로 실행됩니다.ping 실행 파일의 허가를 통해 +s 플래그와 루트에 속하는 프로세스가 표시됩니다.즉, 루트는 루트로 실행됩니다.ls -liat를 실행하여 ping이 있는 곳을 확인합니다.
따라서 InetAddress.getByName("www.google.com")을 루트로 실행하면 isReachable(5000)이 true로 반환됩니다.
ICMP(ping에서 사용되는 프로토콜)에서 사용되는 원시 소켓에 대한 적절한 허가가 필요합니다.
InetAddress.getByName은 ping만큼 신뢰성이 높지만 프로세스를 올바르게 실행하려면 프로세스에 대한 적절한 권한이 필요합니다.
컴퓨터에 PING을 실행할 수 있으므로 Java 프로세스는 검사를 수행할 수 있는 충분한 권한으로 실행됩니다.아마도 낮은 범위의 포트를 사용했기 때문일 것입니다.sudo/superuser로 Java 프로그램을 실행한다면 분명 작동할 것입니다.
인터넷 접속을 테스트하는 유일한 신뢰성 있는 방법은 실제로 접속하여 파일을 다운로드하거나 exec() 경유로 OS ping 콜 출력을 해석하는 것입니다.ping 종료 코드에는 의존할 수 없습니다.isReachable()은 불량입니다.
ping 명령어가 올바르게 실행되면 0이 반환되므로 ping 종료 코드에는 의존할 수 없습니다.유감스럽게도 타겟호스트에 도달할 수 없지만 홈 ADSL 라우터로부터 「Destination host unreachable」을 취득한 경우 ping은 정상적으로 실행됩니다.이는 성공적인 적중으로 간주되는 일종의 응답이므로 종료 코드 = 0입니다. Windows 시스템에 있는 경우에도 추가해야 합니다.*nix를 선택하지 않았습니다.
private boolean isReachable(int nping, int wping, String ipping) throws Exception {
int nReceived = 0;
int nLost = 0;
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("ping -n " + nping + " -w " + wping + " " + ipping);
Scanner scanner = new Scanner(process.getInputStream());
process.waitFor();
ArrayList<String> strings = new ArrayList<>();
String data = "";
//
while (scanner.hasNextLine()) {
String string = scanner.nextLine();
data = data + string + "\n";
strings.add(string);
}
if (data.contains("IP address must be specified.")
|| (data.contains("Ping request could not find host " + ipping + ".")
|| data.contains("Please check the name and try again."))) {
throw new Exception(data);
} else if (nping > strings.size()) {
throw new Exception(data);
}
int index = 2;
for (int i = index; i < nping + index; i++) {
String string = strings.get(i);
if (string.contains("Destination host unreachable.")) {
nLost++;
} else if (string.contains("Request timed out.")) {
nLost++;
} else if (string.contains("bytes") && string.contains("time") && string.contains("TTL")) {
nReceived++;
} else {
}
}
return nReceived > 0;
}
nping은 사용 중인 네트워크 또는 시스템이 더 큰 nping 번호를 선택하는 경우 ip(ping)에 대한 ping 시도 횟수입니다.
wping은 ip에서 pong을 기다리는 시간이며 2000ms로 설정할 수 있습니다.
이 방법을 사용하기 위해 다음과 같이 쓸 수 있습니다.
isReachable(5, 2000, "192.168.7.93");
또는 다음과 같은 방법을 사용합니다.
public static boolean exists(final String host)
{
try
{
InetAddress.getByName(host);
return true;
}
catch (final UnknownHostException exception)
{
exception.printStackTrace();
// Handler
}
return false;
}
InetAddress.isReachable
는 플래피하며 ping할 수 있는 주소에 도달할 수 없는 경우가 있습니다.
다음을 시도했습니다.
ping -c 1 <fqdn>
체크해 주세요.exit status
.
내가 시도했던 모든 사건들에 효과가 있어InetAddress.isReachable
동작하지 않습니다.
인터넷을 체크하려면
public boolean isInternetAvailable() {
try {
InetAddress ipAddr = InetAddress.getByName("google.com");
//You can replace it with your name
return !ipAddr.equals("");
} catch (Exception e1) {
try {
Process p1 = java.lang.Runtime.getRuntime().exec("/system/bin/ping -W 1 -c 1 www.google.com");
int returnVal = 0;
returnVal = p1.waitFor();
boolean reachable = (returnVal==0);
return reachable;
} catch (Exception e2) {
e2.printStackTrace();
return false;
}
}
}
네트워크 연결을 확인하려면
private boolean isNetworkConnected() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
return cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnected();
}
isReachable은 (WireShark에 의한) TCP 프로토콜을 사용하고 있기 때문에 ping 명령어는 ICMP 프로토콜을 사용하고 있습니다.true를 반환하려면 7 포트를 열어야 합니다.
언급URL : https://stackoverflow.com/questions/9922543/why-does-inetaddress-isreachable-return-false-when-i-can-ping-the-ip-address
'programing' 카테고리의 다른 글
Composer create-project와 함께 특정 larabel 버전 설치 (0) | 2022.09.19 |
---|---|
jUnit의 다중 RunWith 문 (0) | 2022.09.19 |
여러 체크박스에서 $_POST 가져오기 (0) | 2022.09.19 |
GROUP_CONCAT를 사용하여 짝수와 홀수를 분할하는 쿼리 (0) | 2022.09.19 |
2개의 어레이가 Foreach 루프에 있음 (0) | 2022.09.19 |