JavaScriptからサーバーにpingすることはできますか?


152

リモートサーバーがオンラインかどうかを確認する必要があるWebアプリを作成しています。コマンドラインから実行すると、ページの読み込みが60秒に達します(8エントリの場合、より多くの場合に比例してスケーリングされます)。

私はユーザー側のpingのルートに行くことにしました。このようにして、ページをロードし、コンテンツを参照している間、「サーバーがオンラインになっている」データを待つだけです。

誰かが上記の質問に対する答えを持っている場合、または私のページの読み込みを高速に保つための解決策を知っている場合は、間違いなく感謝します。

回答:


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

  }
}

これは、私がテストしたすべてのタイプのサーバー(Webサーバー、FTPサーバー、およびゲームサーバー)で機能します。また、ポートで動作します。失敗したユースケースに遭遇した場合は、コメントに投稿してください。回答を更新します。

更新:以前のリンクが削除されました。誰かが上記を見つけたり実装したりした場合は、コメントしてください。答えに追加します。

更新2:@tranteはjsFiddleを提供するのに十分良かったです。

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

更新3:@Jonathonが実装を含むGitHubリポジトリを作成しました。

https://github.com/jdfreder/pingjs

Update 4:この実装は信頼性がないように見えます。人々はまた、Chromeがすべてをサポートしなくなったため、net::ERR_NAME_NOT_RESOLVEDエラーをスローしたと報告しています。誰かが別の解決策を検証できれば、私はそれを受け入れられた回答とします。


48
これは私が使ってきたものです。ただし、欠点が1つあり、それは「イメージ」がキャッシュされることです。最初に特定のIPに対してpingを実行すると、304ミリ秒が返されますが、ページを再読み込みせずにもう一度pingを実行すると、代わりに2ミリ秒が返されます。これは"/?cachebreaker="+new Date().getTime();、必要に応じてimg srcの最後にa を追加することで回避できます。
Meshaal 2012

2
これは私にとっては機能しません。既知の不正なホスト名の結果、Pingリクエストはホストを見つけられませんでした...。しかし、onerrorは「良い」ので、これはそれが反応したと言います
Maslow

5
より多くのテストにより、これは完全に信頼できないことが明らかになりました。
2015年

2
@Jonathonが作成したPing APIは、すべてを正常にpingします。存在しないサイトやランダムなキャラクター。
IE5Master 2016

2
Ping APIは実際には常にonerrorで失敗します。ただし、ターゲットURLが画像を表す場合は、onloadを起動します。CORSチェックをバイパスします。
マーティンヴィスニー2017

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
  }

}


私はこのトリッキーなソリューションが好きです。数を返すのではなく、ピンポン用の関数を提供する必要があることは、私には少し奇妙ですが実行可能です。
ニック

@armen:ping()の3番目の引数として関数を指定する必要があります。この引数の値は、関数内ではpongと呼ばれます。
finitud 2013

2
ping("example.com", "77", function(m){ console.log("It took "+m+" miliseconds."); }).....例の呼び出し
jave.web '18年

@Nick:これは非同期のものなので、メソッドが戻る時点では、onreadystatechangeまだ発生していません。つまり、状態が変化したときにピックアップするコールバックが必要です。
2016

ホストに何を選択しても、pong()が呼び出されます。ping(test.zzzzzzzzz、 "77"、function(m){console.log( "It +" m + "miliseconds。");})は、 "67ミリ秒かかりました。"と出力します。ping(stackoverflow.com、 "80"、function(m){console.log( "Itかかりました" + m + "ミリ秒。");})CORS-Error:developer.mozilla.org/en-US/docs/Web/ HTTP / CORS / Errors /… リモートコンピュータがオンラインかどうかをこのコードで確認する方法がわかりません。
Tux

18

あなたはこれを試すことができます:

ping.htmlをサーバーに配置し、コンテンツを含めても含めなくても、JavaScriptでは次のように実行します。

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

1
私がpingしているサーバーは自分のものではないため、そのオプションはありません。ありがとう。
Chuck Callebs

9
@dlchambers CORSによるものではなく、ドメイン間のポリシーによるものです。CORSを使用すると、サーバーはオリジンを指定でき、さらにブラウザーでサポートする必要があります。クロスドメインの問題のようです。
Royi Namir 2013

CORSのため、HEADタイプのリクエストも機能しません。Chromium 55でテストしました。たとえば、net :: CONNECTION_REFUSEDの場合と同じように、httpコード0で同じエラーを受け取ります。
マーティンヴィスニー2017

これはもっとクロスブラウザです。
ガブリエル

14

JavaScriptで直接「ping」することはできません。他のいくつかの方法があるかもしれません:

  • アヤックス
  • isReachableでの Javaアプレットの使用
  • pingを実行し、AJAXを使用してサーバーサイドスクリプトと通信するサーバーサイドスクリプトを作成する
  • フラッシュでpingを実行できる場合もあります(actionscript)

1
JavaのisReachableは非常に信頼性が低くなります。しかし、2018年であり、Javaアプレットはとにかく時代遅れです。
dreua

8

ブラウザのJavascriptでは通常のpingを実行できませんが、リモートサーバーから画像を読み込むなどして、リモートサーバーが稼働しているかどうかを確認できます。ロードに失敗した場合->サーバーがダウンしています。

onload-eventを使用して、読み込み時間を計算することもできます。次に、onloadイベントの使用例を示します。


4
残念なことに、私がpingしているサーバーはWebサーバーではありません。それらはゲームサーバーです。
Chuck Callebs

1
次に、サーバー側でpingを実行する必要があります。または、軽量のhttpサーバーを検討することもできます。
Epeli

pingを集約する方法を知っていますか?それが私の主なスローダウンであり、1つの要求が完了するのを待ってから、他の要求が開始されます。
Chuck Callebs

サーバーを同時にpingする必要があります。選択、スレッド、またはプロセスでそれを実現できます。本当にハードコアなソリューションの場合は、Eventmachineを使用できます。
Epeli

1
コマンドラインpingコマンドを利用することを検討するかもしれません。それは産業の強みです。または、さまざまな種類のハートビートチェックを使用して、ホストが実行されているかどうかを監視するあらゆる種類の無料/オープンソースアプリがあります。
ティンマン

7

WebSocketソリューションの提案...

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 2015年

1
これは、websocketプロトコルを使用しますが、実際には接続を待機しているwebsocketサーバーがないと想定しています。これは、「古いIP」をpingするためだけのものです。
Antony Woods

しかし、どうすればWebSocketがサポートされていないのか、実際にエラーが発生したのかを検出できますか?:)
jave.web 2015年

ポート80でwebsocket接続を受け入れることができる IPにpingを送信できるほど運が悪いと思う場合は、はい、そのコールバックに追加isUp();する必要があります。または、明らかにwebsocket-y以外のポートを追加することでそれを軽減します。
Antony Woods

私がこれに投票したのは、WebSocketサーバーが再起動したときに何が起きるかの解決策を探してここに来たためです。この回答から、ソケットのエラーハンドラーでsetTimeoutを実行して再接続(ビジー待機)を試みることができることがわかりました。おそらくベストプラクティスではありませんが、私の問題は解決します。:)
mynameisnafe

6

リクエストを高速に保つには、pingのサーバー側の結果をキャッシュし、数分ごとにpingファイルまたはデータベースを更新します(または正確にしたい場合)。cronを使用して、8つのpingでシェルコマンドを実行し、出力をファイルに書き込むことができます。Webサーバーはこのファイルをビューに含めます。


これは、正確な結果を得るための最も信頼できる方法だと思います。しかし、それはまだサーバー上でいくつかの作業を必要とするので、それは賢い方法ではないと思います。
チェタバハナ2015年

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

これにより、サーバーが存在するかどうかのtrue / falseの指示が返されます。

応答時間が必要な場合は、少し変更するだけで済みます。

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

このリンクで質問に答えることができますが、回答の重要な部分をここに含め、参照用のリンクを提供することをお勧めします。リンクされたページが変更されると、リンクのみの回答が無効になる可能性があります。
フォンブランド、2014年

1
これは優れたソリューションですが、残念ながら、yahooドメインクエリサービスはさまざまな結果を返すようです。たとえば、次のURLを試すと、begin-download .com beginfreedownload .comは登録されていないものとして返されますが、これらのURLにアクセスすると、明らかに登録されています。ここで何が起こっているのですか?(私はこれらの例でドメイン名にスペースを追加しました、それはグーグルジュースを与えるのを避けるためです。私のテストではそれらにスペースがありませ
んでし

Yahoo!にリクエストを送信しています。API、あなたのマシンからリクエストをした場合、pingは同じではありません。これは意味がありません
Andre Figueiredo 2016年

これが原因No 'Access-Control-Allow-Origin' header is present on the requested resource. Originで成功のコールバックが呼び出されることはありません
vladkras

4

標準的なpingの問題は、それらがICMPであることです。多くの場所では、セキュリティとトラフィックの理由で通過できません。それは失敗を説明するかもしれません。

Ruby 1.9より前のping.rbバージョンにはTCPベースのがあり、これはRuby 1.9以降で実行されます。1.8.7のインストールから別の場所にコピーするだけです。ホームルーターにpingを実行することで動作することを確認しました。


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や道場なども使用できます...


1
「XMLHttpRequestはIPを読み込めません。要求されたリソースに 'Access-Control-Allow-Origin'ヘッダーがありません。したがって、オリジン 'ip2'はアクセスを許可されていません。CORSによってブロックされました。httpステータス0で成功するため、たとえば、これをnet :: ERR_CONNECTION_REFUSEDと区別することができません
Martin Vysny

0

実行しているRubyのバージョンがわかりませんが、JavaScriptの代わりにRubyのpingを実装してみましたか?http://raa.ruby-lang.org/project/net-ping/


ええ、私はそれを試しましたが、Webサーバーに関係なく、pingは常にfalseに戻りました。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になります。


D:いいえ、それは永久に移動301を返しています)、必要な不足している)... 1ではありません2
ミハルMikyJankovský

-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 2013

一体何ですか?Active 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

それよりもずっと簡単かもしれません。ページをロードしたい場合は、外部ページの可用性またはコンテンツを確認して、他のWebページアクティビティをトリガーする場合、次のようにJavaScriptと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>

それでうまくいくはずです。

トリガーされるJavaScriptには、clearInterval(stopmelater)が含まれている必要があります

それがうまくいくか教えてください

ジェリー


2
前に言ったように、これらは私がpingしているWebサーバーではありません。これらはゲームサーバーです。HTTPリクエストには応答しません。:(
チャック・カレブ

おい、
file_get_contents

$ ip = $ _SERVER ['127.0.0.1']; exec( "ping -n 4 $ ip 2>&1"、$ output、$ retval); if($ retval!= 0){echo "no!"; } else {echo "yes!"; }
ジェリーウィッキー

4
これはPHPの質問ではありません。これはJavaScriptの質問です。PHPは使用していません。
Chuck Callebs

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を使用するOPにどのような支援を与えましたか?
ビフォーブ2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.