Javascript에서 서버를 핑 (ping) 할 수 있습니까?


152

원격 서버가 온라인인지 여부를 확인 해야하는 웹 응용 프로그램을 만들고 있습니다. 명령 줄에서 실행하면 페이지로드가 최대 60 초까지 올라갑니다 (8 개 항목의 경우 더 많이 확장됩니다).

나는 사용자의 끝에 핑 경로를 가기로 결정했다. 이렇게하면 페이지를로드 할 수 있으며 내 콘텐츠를 탐색하는 동안 "서버가 온라인 상태입니다"데이터를 기다리도록 할 수 있습니다.

위의 질문에 대한 답변이 있거나 페이지를 빠르게로드 할 수있는 솔루션을 알고 있다면 분명히 감사하겠습니다.

답변:


134

네이티브 Image객체를 매우 영리하게 사용하여 이것을 달성하는 사람을 발견했습니다 .

소스에서 이것은 주요 기능입니다 (소스의 다른 부분에 의존하지만 아이디어를 얻습니다).

function Pinger_ping(ip, callback) {

  if(!this.inUse) {

    this.inUse = true;
    this.callback = callback
    this.ip = ip;

    var _that = this;

    this.img = new Image();

    this.img.onload = function() {_that.good();};
    this.img.onerror = function() {_that.good();};

    this.start = new Date().getTime();
    this.img.src = "http://" + ip;
    this.timer = setTimeout(function() { _that.bad();}, 1500);

  }
}

이것은 내가 테스트 한 모든 유형의 서버 (웹 서버, ftp 서버 및 게임 서버)에서 작동합니다. 포트와도 작동합니다. 누구든지 사용 사례가 실패하면 의견을 게시하면 답변을 업데이트하겠습니다.

업데이트 : 이전 링크가 제거되었습니다. 위의 내용을 찾거나 구현하는 사람은 의견을 말하고 답변에 추가하겠습니다.

업데이트 2 : @trante는 jsFiddle을 제공하기에 충분했습니다.

http://jsfiddle.net/GSSCD/203/

업데이트 3 : @Jonathon은 구현으로 GitHub 저장소를 만들었습니다.

https://github.com/jdfreder/pingjs

업데이트 4 :이 구현이 더 이상 신뢰할 수없는 것처럼 보입니다. 사람들은 또한 Chrome이 더 이상 모든 것을 지원하지 않아 net::ERR_NAME_NOT_RESOLVED오류가 발생 한다고보고합니다 . 누군가가 다른 해결책을 확인할 수 있다면 나는 그것을 정답으로 넣을 것입니다.


48
이것이 내가 사용한 것입니다. 그러나 하나의 결함이 있으며 "이미지"가 캐시된다는 것입니다. 주어진 IP를 처음에 핑하면 304ms가 발생하지만 페이지를 다시로드하지 않고 두 번째로 핑하면 2ms가 발생합니다. "/?cachebreaker="+new Date().getTime();필요한 경우 img src의 끝에 a 를 추가하면 피할 수 있습니다 .
— Meshaal

2
이것은 나를 위해 작동하지 않습니다. 알려진 잘못된 호스트 이름으로 인해 Ping 요청에서 host를 찾을 수 없습니다 .... 그러나 onerror가 '좋은'것이기 때문에 이것은 응답했다
— Maslow

5
더 많은 테스트 결과에 따르면 이것이 완전히 신뢰할 수 없다는 것이 밝혀졌습니다.
— Leo

2
@Jonathon이 만든 Ping API는 모든 것을 ping합니다. 존재하지 않는 사이트 및 임의의 문자.
— IE5Master

2
Ping API는 실제로 항상 onerror와 함께 실패합니다. 그러나 대상 URL이 이미지를 나타내면 onload가 발생하여 멋집니다! CORS 검사를 무시합니다.
— Martin Vysny

20

Ping은 ICMP이지만 원격 서버에 열린 TCP 포트가 있으면 다음과 같이 얻을 수 있습니다.

function ping(host, port, pong) {

  var started = new Date().getTime();

  var http = new XMLHttpRequest();

  http.open("GET", "http://" + host + ":" + port, /*async*/true);
  http.onreadystatechange = function() {
    if (http.readyState == 4) {
      var ended = new Date().getTime();

      var milliseconds = ended - started;

      if (pong != null) {
        pong(milliseconds);
      }
    }
  };
  try {
    http.send(null);
  } catch(exception) {
    // this is expected
  }

}


이 까다로운 솔루션이 마음에 듭니다. 숫자를 반환하는 대신 퐁에 함수를 제공 해야하는 것은 조금 이상하지만 실행 가능합니다.
— Nick

@armen : ping ()의 세 번째 인수로 함수를 제공해야합니다.이 인수의 값을 함수 내에서 pong이라고합니다.
— finitud

2
ping("example.com", "77", function(m){ console.log("It took "+m+" miliseconds."); })..... 전화 예
— jave.web

@ Nick : 이것은 비동기식이므로 메소드가 반환 될 때 onreadystatechange아직 실행되지 않았습니다. 즉, 상태가 변경 될 때 픽업하려면 콜백이 필요합니다.
— awe

내가 호스트를 위해 무엇을 선택하든 pong ()이 호출됩니다. ping ( test.zzzzzzzzz, "77", function (m) {console.log ( ""+ m + "밀리 초가 걸렸습니다.");}) "67 밀리 초가 걸렸습니다." ping ( stackoverflow.com, "80", function (m) {console.log ( ""+ m + "밀리 초가 걸렸습니다.");}) CORS-Error : developer.mozilla.org/en-US/docs/Web/ HTTP / CORS / Errors /… 원격 컴퓨터가 온라인 상태 일 때이 코드를 어떻게 확인할 수 있는지 모르겠습니다.
— Tux

18

당신은 이것을 시도 할 수 있습니다 :

내용이 있거나없는 서버 에 ping.html 을 넣고 자바 스크립트에서 다음과 같이하십시오.

<script>
    function ping(){
       $.ajax({
          url: 'ping.html',
          success: function(result){
             alert('reply');
          },     
          error: function(result){
              alert('timeout/error');
          }
       });
    }
</script>

1
핑하는 서버는 내 서버가 아니므로 해당 옵션이 없습니다. 그래도 고마워.
— Chuck Callebs

9
@dlchambers CORS로 인한 것이 아니라 교차 도메인 poilicy로 인해 발생합니다. CORS를 사용하면 서버가 원점을 지정할 수 있으며 브라우저에서 원점을 지원해야합니다. 도메인 간 문제와 비슷합니다.
— Royi Namir

CORS로 인해 HEAD 유형 요청이 작동하지 않습니다. Chromium 55로 테스트했습니다. 예를 들어 net :: CONNECTION_REFUSED의 경우와 같이 http 코드 0으로 동일한 오류가 수신됩니다.
— Martin Vysny

이것은 더 크로스 브라우저입니다.
— Gabriel

14

자바 스크립트에서는 직접 "핑"할 수 없습니다. 몇 가지 다른 방법이있을 수 있습니다.

  • 아약스
  • isReachable 과 함께 Java 애플릿 사용
  • Ping을 수행하고 AJAX를 사용하여 서버 측 스크립트와 통신하는 서버 측 스크립트 작성
  • 플래시로 핑할 수도 있습니다 (액션 스크립트)

1
Java의 isReachable은 매우 신뢰할 수 없습니다 ...하지만 2018 년이었고 Java 애플릿은 구식입니다.
— dreua

8

브라우저 Javascript에서 정기적으로 핑을 수행 할 수는 없지만 원격 서버에서 이미지를로드하는 등의 방법으로 원격 서버가 활성 상태인지 확인할 수 있습니다. 로딩이 실패하면-> 서버 다운.

onload-event를 사용하여 로딩 시간을 계산할 수도 있습니다. 다음은 onload 이벤트를 사용하는 방법 의 예 입니다.


4
불행히도 핑하는 서버는 웹 서버가 아닙니다. 그들은 게임 서버입니다.
— Chuck Callebs

1
그런 다음 서버 측에서 핑을 수행해야합니다. 그렇지 않으면 가벼운 http 서버를 고려할 수 있습니다.
— Epeli

집계 핑을 수행하는 방법을 알고 있습니까? 그것은 하나의 요청이 다른 요청이 시작되기 전에 완료되기를 기다리는 나의 주요 둔화입니다.
— Chuck Callebs

서버를 동시에 핑해야합니다. 선택, 스레드 또는 프로세스로이를 달성 할 수 있습니다. 실제로 하드 코어 솔루션의 경우 Eventmachine을 사용할 수 있습니다.
— Epeli

1
명령 행 ping명령 을 활용할 수 있습니다 . 산업의 힘입니다. 또는 다양한 유형의 하트 비트 검사를 사용하여 호스트가 실행 중인지 모니터링 할 수있는 모든 종류의 무료 / 오픈 소스 앱이 있습니다.
— 틴맨

7

웹 소켓 솔루션을 사용하여 피칭 ...

function ping(ip, isUp, isDown) {
  var ws = new WebSocket("ws://" + ip);
  ws.onerror = function(e){
    isUp();
    ws = null;
  };
  setTimeout(function() { 
    if(ws != null) {
      ws.close();
      ws = null;
      isDown();
    }
  },2000);
}

isUp();호출이 onopen이벤트 핸들러 에 있어야합니까 ? :)
— jave.web

1
웹 소켓 프로토콜을 사용하지만 실제로 연결을 기다리는 웹 소켓 서버가 없다고 가정 합니다. 이것은 '오래된 IP'를 핑하기위한 것입니다.
— Antony Woods

그러나 WebSocket이 지원되지 않거나 실제로 어떤 오류가 있는지 감지하는 방법은 무엇입니까? :)
— jave.web

당신은 IP 핑 불운 충분히있을거야 생각한다면 수 포트 80에 웹 소켓 연결을 수락을하고 그래, 당신은해야한다 또한 추가 isUp();하는 콜백. 또는 비 websocket-y 포트를 명확하게 추가하여 완화하십시오.
— Antony Woods

웹 소켓 서버가 재부팅 될 때 발생하는 문제에 대한 해결책을 찾기 위해 여기에 왔 으므로이 답변에 따르면 소켓의 오류 처리기에서 timeTime을 설정하고 다시 연결을 시도 할 수 있습니다 (바쁨 대기). 아마도 모범 사례는 아니지만 내 문제를 해결합니다. :)
— mynameisnafe

6

요청을 빠르게 유지하려면 핑의 서버 측 결과를 캐시하고 2 분마다 (또는 원하는대로) 핑 파일 또는 데이터베이스를 업데이트하십시오. cron을 사용하여 8 핑으로 쉘 명령을 실행하고 출력을 파일에 쓸 수 있습니다. 웹 서버는이 파일을보기에 포함시킵니다.


이것이 정확한 결과를 위해 가능한 가장 신뢰할 수있는 방법이라고 생각합니다. 그러나 여전히 서버에서 일부 작업이 필요하기 때문에 똑똑하지 않다고 말할 것입니다.
— Chetabahana

5

보고자하는 것이 서버가 "존재"하는지 여부 인 경우 다음을 사용할 수 있습니다.

function isValidURL(url) {
    var encodedURL = encodeURIComponent(url);
    var isValid = false;

    $.ajax({
      url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22" + encodedURL + "%22&format=json",
      type: "get",
      async: false,
      dataType: "json",
      success: function(data) {
        isValid = data.query.results != null;
      },
      error: function(){
        isValid = false;
      }
    });

    return isValid;
}

서버가 존재하는지 여부에 대한 참 / 거짓 표시를 반환합니다.

응답 시간을 원하는 경우 약간 수정하면됩니다.

function ping(url) {
    var encodedURL = encodeURIComponent(url);
    var startDate = new Date();
    var endDate = null;
    $.ajax({
      url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22" + encodedURL + "%22&format=json",
      type: "get",
      async: false,
      dataType: "json",
      success: function(data) {
        if (data.query.results != null) {
            endDate = new Date();
        } else {
            endDate = null;
        }
      },
      error: function(){
        endDate = null;
      }
    });

    if (endDate == null) {
        throw "Not responsive...";
    }

    return endDate.getTime() - startDate.getTime();
}

그런 다음 사용법이 간단합니다.

var isValid = isValidURL("http://example.com");
alert(isValid ? "Valid URL!!!" : "Damn...");

또는:

var responseInMillis = ping("example.com");
alert(responseInMillis);

이 링크가 질문에 대한 답변을 제공 할 수 있지만 여기에 답변의 필수 부분을 포함시키고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않을 수 있습니다.
— vonbrand

1
이것은 훌륭한 솔루션이지만 불행히도 야후 도메인 쿼리 서비스는 다양한 결과를 제공하는 것으로 보입니다. 예를 들어 다음 URL을 시도하면 begin-download .com beginfreedownload .com은 등록되지 않은 상태로 돌아 오지만 해당 URL로 이동하면 명확하게 등록됩니다. 여기서 무슨 일이 일어나고 있습니까? (이 예제에서는 도메인 이름에 공백을 추가했습니다. 단지 구글 쥬스를주지 않기 위해서입니다. 내 테스트에는 공백이 없었습니다)
— user280109

Yahoo!에 요청 중입니다! 컴퓨터에서 요청하면 API, 핑은 동일하지 않습니다. 이것은 말이되지 않습니다
— Andre Figueiredo

이 원인 No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin과 성공 콜백이 호출되지 않습니다
— vladkras


4

여기 CORS에 대한 많은 미친 답변이 있습니다-

http HEAD 요청 (GET과 같지만 페이로드는 없음)을 수행 할 수 있습니다. https://ochronus.com/http-head-request-good-uses/를 참조 하십시오

프리 플라이트 확인이 필요하지 않습니다. 혼동은 사양의 이전 버전으로 인한 것입니다 . 교차 출처 HEAD 요청에 프리 플라이트 확인이 필요한 이유를 참조 하십시오.

따라서 jQuery 라이브러리를 사용하고 있지만 말하지 않은 위의 답변을 사용할 수 있습니다.

type: 'HEAD'

--->

<script>
    function ping(){
       $.ajax({
          url: 'ping.html',
          type: 'HEAD',
          success: function(result){
             alert('reply');
          },     
          error: function(result){
              alert('timeout/error');
          }
       });
    }
</script>

물론 바닐라 js 또는 dojo 또는 무엇이든 사용할 수 있습니다 ...


1
"XMLHttpRequest는 IP를로드 할 수 없습니다. 요청 된 리소스에 'Access-Control-Allow-Origin'헤더가 없습니다. 따라서 원본 'ip2'는 액세스 할 수 없습니다."와 함께 HEAD 요청을 보내는 데 여전히 실패합니다. CORS에 의해 차단되었습니다. http 상태 0으로 성공하면 net :: ERR_CONNECTION_REFUSED와 구별 할 수 없습니다. 예
— Martin Vysny

0

실행중인 Ruby 버전을 모르지만 javascript 대신 ruby에 대해 ping을 구현하려고 시도 했습니까? http://raa.ruby-lang.org/project/net-ping/


그래, 나는 그것을 시도했지만 웹 서버에 관계없이 핑은 항상 거짓으로 돌아왔다. ping server.com구문을 사용하도록 변경했습니다 .
— Chuck Callebs

-1
let webSite = 'https://google.com/' 
https.get(webSite, function (res) {
    // If you get here, you have a response.
    // If you want, you can check the status code here to verify that it's `200` or some other `2xx`.
    console.log(webSite + ' ' + res.statusCode)
}).on('error', function(e) {
    // Here, an error occurred.  Check `e` for the error.
    console.log(e.code)
});;

노드로 이것을 실행하면 Google이 다운되지 않는 한 콘솔 로그 200이됩니다.


아니, 그것은 아니다 ... 1) 당신이 요구 누락, 2) 301 영구적으로 이동 반환 : D
— Michal Miky Jankovský

-1
const ping = (url, timeout = 6000) => {
  return new Promise((reslove, reject) => {
    const urlRule = new RegExp('(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]');
    if (!urlRule.test(url)) reject('invalid url');
    try {
      fetch(url)
        .then(() => reslove(true))
        .catch(() => reslove(false));
      setTimeout(() => {
        reslove(false);
      }, timeout);
    } catch (e) {
      reject(e);
    }
  });
};

이처럼 사용하십시오 :

ping('https://stackoverflow.com/')
  .then(res=>console.log(res))
  .catch(e=>console.log(e))

-4

다음을 사용하여 javaScript에서 DOS ping.exe 명령을 실행할 수 있습니다.

function ping(ip)
{
    var input = "";
    var WshShell = new ActiveXObject("WScript.Shell");
    var oExec = WshShell.Exec("c:/windows/system32/ping.exe " + ip);

    while (!oExec.StdOut.AtEndOfStream)
    {
            input += oExec.StdOut.ReadLine() + "<br />";
    }
    return input;
}

이것이 요청 된 것입니까, 아니면 뭔가 빠졌습니까?


4
이것은 불행히도 IE에서만 작동하며 Windows 서버에서만 작동합니다. 더 좋은 옵션은 AJAX를 사용하여 서버 측 스크립트를 실행하는 것입니다.
— Andrew Grothe

이런 젠장? 액티브 X 객체는 사용자의 파일 시스템에서 실행될 수 있습니까 (Win 서버의 IE에서)? 나는 ActiveX로 작업하지 않았지만 그것을 상상하지 못했습니다 ...
— Julix

-6

그냥 교체

file_get_contents

와

$ip = $_SERVER['xxx.xxx.xxx.xxx'];
exec("ping -n 4 $ip 2>&1", $output, $retval);
if ($retval != 0) { 
  echo "no!"; 
} 
else{ 
  echo "yes!"; 
}

1
새로운 '부분적인' 답변 을 추가하는 대신 이전 답변을 편집해야합니다 .
— Artemix

-8

모든 것보다 훨씬 쉬울 수 있습니다. 페이지를로드하고 다른 웹 페이지 활동을 트리거하기 위해 일부 외국 페이지의 가용성 또는 내용을 확인하려면 이와 같은 자바 스크립트 및 PHP 만 사용하여 수행 할 수 있습니다.

yourpage.php

<?php
if (isset($_GET['urlget'])){
  if ($_GET['urlget']!=''){
    $foreignpage= file_get_contents('http://www.foreignpage.html');
    // you could also use curl for more fancy internet queries or if http wrappers aren't active in your php.ini
    // parse $foreignpage for data that indicates your page should proceed
    echo $foreignpage; // or a portion of it as you parsed
    exit();  // this is very important  otherwise you'll get the contents of your own page returned back to you on each call
  }
}
?>

<html>
  mypage html content
  ...

<script>
var stopmelater= setInterval("getforeignurl('?urlget=doesntmatter')", 2000);

function getforeignurl(url){
  var handle= browserspec();
  handle.open('GET', url, false);
  handle.send();
  var returnedPageContents= handle.responseText;
  // parse page contents for what your looking and trigger javascript events accordingly.
  // use handle.open('GET', url, true) to allow javascript to continue executing. must provide a callback function to accept the page contents with handle.onreadystatechange()
}
function browserspec(){
  if (window.XMLHttpRequest){
    return new XMLHttpRequest();
  }else{
    return new ActiveXObject("Microsoft.XMLHTTP");
  }
}

</script>

그렇게해야합니다.

트리거 된 자바 스크립트에는 clearInterval (stopmelater)이 포함되어야합니다.

그것이 당신을 위해 작동하는지 알려주세요

작은 권총


2
앞에서 말했듯이 이것들은 내가 핑하는 웹 서버가 아닙니다. 이것들은 게임 서버입니다. HTTP 요청에 응답하지 않습니다. :(
— Chuck Callebs

친구, 그냥 file_get_contents를
— Jerry Wickey로

$ ip = $ _SERVER [ '127.0.0.1']; exec ( "ping -n 4 $ ip 2> & 1", $ output, $ retval); if ($ retval! = 0) {echo "no!"; } else {echo "예!"; }
— Jerry Wickey

4
이것은 PHP 질문이 아닙니다. 이것은 JavaScript 질문입니다. PHP를 사용하지 않습니다.
— 척 칼라 브스

1
게시물에 서명이나 태그 라인을 사용하지 마십시오. 삭제됩니다. 자세한 내용은 FAQ 를 참조하십시오.
— Artemix

-13

웹 페이지에서 PHP를 사용해보십시오 ... 다음과 같은 것 :

<html><body>
<form method="post" name="pingform" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<h1>Host to ping:</h1>
<input type="text" name="tgt_host" value='<?php echo $_POST['tgt_host']; ?>'><br>
<input type="submit" name="submit" value="Submit" >
</form></body>
</html>
<?php

$tgt_host = $_POST['tgt_host'];
$output = shell_exec('ping -c 10 '. $tgt_host.');

echo "<html><body style=\"background-color:#0080c0\">
<script type=\"text/javascript\" language=\"javascript\">alert(\"Ping Results: " . $output . ".\");</script>
</body></html>";

?>

이것은 테스트되지 않았으므로 오타 등이있을 수 있지만 작동 할 것이라고 확신합니다. 너무 향상 될 수 ...


5
OP의 태그에 따르면 이것은 실제로 Ruby on Rails 질문이므로 PHP를 사용하는 것은 좋은 해결책이 아닙니다.
— Tin Man

1
여기서 논쟁을 시작하지는 않지만이 포럼이 도움이되지 않습니까?
— Chris

5
@Chris PHP 응용 프로그램에서 Ruby 및 JS를 사용하는 사람은 PHP 코드를 제공하여 OP에게 어떤 도움을 주었습니까?
— biphobe
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.