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.