IP 주소를 ping 할 수 있는데 InetAddress.isReachable이 false를 반환하는 이유는 무엇입니까?


96
InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));

isReachable돌아 오나요 false? IP를 핑할 수 있습니다.



1
비슷합니다. 하지만 문제를 해결할 단서를 찾을 수 없어서 여기에서 다시 올렸습니다. 상기시켜 주셔서 감사합니다!
jiafu

2
시간 제한을 늘리려 고합니다.
jayunit100

이것은 아주 좋은 질문입니다. 찬성표가 충분하지 않습니다. 내가 찾은 유일한 유사한 질문은 클로저 질문으로 태그가 지정되었으며 대답은 결정적이지 않았습니다.
jayunit100

3
누군가 정확히 isReachable ()이 무엇을하는지 말해 줄 수 있습니까? 그것은 ... 심지어 로컬 호스트 나 false를 반환
세스 키노에게

답변:


73

"의 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이 서버에 한 번만 도달하려고 시도 할 수 있습니다 (터미널에서 사용하던 무한 핑과는 반대로).

호스트에 연결할 수 있으면 0 을 반환 합니다. 그렇지 않으면 반환 값으로 "2"가 표시됩니다.

훨씬 간단하지만 물론 플랫폼에 따라 다릅니다. 이 명령을 사용하는 데 특정 권한 경고가있을 수 있지만 내 컴퓨터에서 작동합니다.


참고 : 1)이 솔루션은 생산 품질이 아닙니다. 약간의 해킹입니다. Google이 다운되거나 인터넷이 일시적으로 느리거나 권한 / 시스템 설정에 약간의 재미가 있더라도 거짓 부정을 반환 할 수 있습니다 (즉, 입력 주소에 도달 할 수 있어도 실패 할 수 있음). 2) isReachable 실패는 미해결 문제입니다. 다시 말하지만, JVM이 호스트에 도달하려고 시도하는 방식으로 인해이 글을 쓰는 시점에 "완벽한"방법이 없음을 나타내는 여러 온라인 리소스가 있습니다.이 작업은 본질적으로 간단하지만 플랫폼 별 작업이라고 생각합니다. , 아직 JVM에 의해 충분히 추상화되지 않았습니다.


접근 방식이 모두 작동하지 않는 @ jayunit100, isReachable실패하고 ping을 사용하여 icmp가 허용되지 않습니까? 지금 어떻게 처리해야하는지 아십니까?
Yuvi

6
@Yuvi Windows를 사용하는 경우 플래그가 다릅니다. -c 대신 -n을 원합니다.
James T Snell

waitFor ()는 반환하는 데 10 초가 걸립니다. Java 7에서 시간 초과를 언급하는 방법이 있습니까?
Jaydev

@Jaydev, 오버로드 된 옵션도 있습니다 : public boolean waitFor(long timeout, TimeUnit unit)in java.lang.Process (@since 1.8)
indivisible

2020-01 현재 문제없이 문제의 예를 실행할 수 있으며 IPv4 1 개와 IPv6 주소 1 개에 대해 "연결됨"으로보고됩니다. 이 버그 는 Java 5.0 b22에서도 수정되었습니다. 아마도 isReachable요즘은 더 신뢰할 수 있습니다.
Lii

54

나는이 같은 질문에 대한 답을 얻기 위해 여기에 왔지만 플랫폼 독립적 인 솔루션을 찾고 있었기 때문에 답이 만족스럽지 않았습니다. 다음은 내가 작성한 코드이며 플랫폼에 독립적이지만 다른 시스템의 열린 포트에 대한 정보가 필요합니다 (대부분의 시간이 있음).

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

2
이것은 훌륭한 플랫폼 독립적 솔루션입니다. 감사합니다!
ivandov

1
나는 행복 내가 :) Sourabh 생각에, 여기에 좋은 방법을 종료 해요
JustADev

그래서, 내가 완전히 이해했는지 확인하기 위해 : 예외가없는 한, 주소에 도달 할 수 있었습니까?
Timmiej93

1
이는 InetAddress.isReachable()포트 7을 통해 이미 수행 한 작업 과 동일합니다 . 단, 후자는 IOExceptions도달 가능성 측면에서 가능한 다양한 의미에 대해 더 지능적 입니다.
론의 후작

1
예 @EJP InetAddress.isReachable()표준 라이브러리에 포트 인수를 포함하도록 오버로드 되면 좋을 것이라고 생각합니다 . 왜 포함되지 않았는지 궁금합니다.
Sourabh Bhat

7

인터넷에 연결되어 있는지 만 확인하려면이 방법을 사용합니다. 인터넷이 연결되어 있으면 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;
    }

2
서버에 웹 서버가 없으면 쓸모가 없습니다. 그것은 전혀 질문에 지정된 조건이 아닙니다.
Fran Marzoa 2014

3

다른 답변은 그렇지 않기 때문에 명시 적으로 언급합니다. isReachable ()의 ping 부분은 Unix에서 루트 액세스가 필요합니다. 그리고 4779367에서 bestsss가 지적한 바와 같이 :

그리고 bash에서 핑이 왜 안되는지 묻는다면 실제로도 필요합니다. ls -l / bin / ping을 수행하십시오.

내 경우에는 루트를 사용하는 것이 옵션이 아니기 때문에 해결책은 내가 관심이있는 특정 서버에 대한 방화벽의 포트 7에 대한 액세스를 허용하는 것이 었습니다.


3

2012 년에 원래 질문을 받았을 때 주가 무엇인지 잘 모르겠습니다.

현재로서는 ping이 루트로 실행됩니다. ping 실행 파일의 인증을 통해 + s 플래그와 루트에 속한 프로세스를 볼 수 있습니다. 즉, 루트로 실행됩니다. ping이있는 위치에서 ls -liat를 실행하면 볼 수 있습니다.

따라서 InetAddress.getByName ( "www.google.com"). isReacheable (5000)을 루트로 실행하면 true를 반환해야합니다.

ICMP (ping에서 사용하는 프로토콜)에서 사용하는 원시 소켓에 대한 적절한 인증이 필요합니다.

InetAddress.getByName은 ping만큼 안정적이지만 제대로 실행하려면 프로세스에 대한 적절한 권한이 필요합니다.


0

인터넷 연결을 테스트하는 유일한 신뢰할 수있는 방법은 실제로 연결하고 파일을 다운로드하거나 exec ()를 통해 OS 핑 호출의 출력을 구문 분석하는 것입니다. ping에 대한 종료 코드에 의존 할 수 없으며 isReachable ()은 쓰레기입니다.

ping 명령이 올바르게 실행되면 0을 반환하므로 ping 종료 코드를 신뢰할 수 없습니다. 안타깝게도 ping은 대상 호스트에 도달 할 수 없지만 홈 ADSL 라우터에서 "Destination host unreachable"을 받으면 올바르게 실행됩니다. 이것은 성공적인 히트로 취급되는 일종의 응답이므로 종료 코드 = 0입니다. 이것이 Windows 시스템에 있음을 추가해야합니다. 확인되지 않음 * nixes.


0
 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을 시도하는 횟수입니다.
wping은 ip에서 pong을 기다리는 시간입니다.
이 방법을 사용하여 2000ms 로 설정할 수 있습니다.

isReachable(5, 2000, "192.168.7.93");

잠재적 인 명령 주입, 실행하기 전에 문자열 입력의 유효성을 검사하십시오
스파이

"일반 실패"오류 메시지도 있습니다. 이것은 또한 특정 창처럼 보입니다. 이 오류 메시지는 다른 언어로 현지화되어 있으므로 이식성이 뛰어납니다.
스파이

이것은 Windows 시스템 용입니다.
Armin Mokri 19.06.30

넵 나는 전에 윈도우에서 본 적이 있습니다
스파이

0

또는 다음과 같이 사용하십시오.

public static boolean exists(final String host)
{
   try
   {
      InetAddress.getByName(host);
      return true;
   }
   catch (final UnknownHostException exception)
   {
      exception.printStackTrace();
      // Handler
   }
   return false;
}

0

InetAddress.isReachable flappy이며 때로는 ping 할 수있는 주소에 대해 연결할 수없는 경우를 반환합니다.

다음을 시도했습니다.

ping -c 1 <fqdn>확인하고 exit status.

작동 InetAddress.isReachable하지 않는 곳에서 시도한 모든 경우에 대해 작동합니다.


-1

컴퓨터를 ping 할 수 있으므로 Java 프로세스는 검사를 수행 할 수있는 충분한 권한으로 실행되어야합니다. 아마도 더 낮은 범위의 포트를 사용했기 때문일 것입니다. sudo / superuser로 Java 프로그램을 실행하면 작동 할 것입니다.


낮은 범위의 포트에 연결 하는 데는 권한이 필요하지 않습니다 .
Marquis of Lorne
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.