Javascript'ten bir sunucuya ping atmak mümkün mü?


152

Uzak sunucuların çevrimiçi olup olmadığını kontrol etmemi gerektiren bir web uygulaması yapıyorum. Komut satırından çalıştırdığımda, sayfa yüküm tam 60 saniyeye kadar çıkıyor (8 giriş için doğrusal olarak daha fazla ölçeklenecek).

Kullanıcının sonunda pingleme rotasına gitmeye karar verdim. Bu şekilde, sayfayı yükleyebilir ve içeriğime göz atarken "sunucu çevrimiçi" verilerini beklemelerini sağlayabilirim.

Birisi yukarıdaki sorunun cevabına sahipse veya sayfamın hızlı yüklenmesini sağlayacak bir çözüm biliyorsa, kesinlikle memnun olurum.

Yanıtlar:


134

Bunu yerel Imagenesnenin çok akıllıca kullanılmasıyla başaran birini buldum .

Kaynaklarından, bu ana işlevdir (kaynağın diğer bölümlerine bağımlıdır, ancak fikri anlarsınız).

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

  }
}

Bu, test ettiğim tüm sunucu türlerinde (web sunucuları, ftp sunucuları ve oyun sunucuları) çalışır. Bağlantı noktaları ile de çalışır. Herhangi biri başarısız bir kullanım durumu ile karşılaşırsa, lütfen yorumlarda yayınlayın ve cevabımı güncelleyeceğim.

Güncelleme : Önceki bağlantı kaldırıldı. Birisi yukarıdakini bulursa veya uygularsa, lütfen yorum yapın ve cevaba ekleyeceğim.

Güncelleme 2 : @Trante bir jsFiddle sağlayacak kadar güzeldi.

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

Güncelleme 3 : @Jonathon uygulama ile bir GitHub repo oluşturdu.

https://github.com/jdfreder/pingjs

Güncelleme 4 : Bu uygulama artık güvenilir değil gibi görünüyor. İnsanlar ayrıca Chrome'un artık hepsini desteklemediğini ve net::ERR_NAME_NOT_RESOLVEDhata verdiğini bildiriyor . Birisi alternatif bir çözümü doğrulayabilirse, bunu kabul edilen cevap olarak koyacağım.


48
Ben bunu kullanıyorum. Bununla birlikte, bir kusuru vardır ve bu "görüntü" önbelleğe alınır. Başlangıçta belirli bir IP'ye ping attığımda, 304 ms alıyorum - ancak bir sayfa yeniden yüklemeden ikinci kez ping yaparsam, bunun yerine 2 ms alırım. "/?cachebreaker="+new Date().getTime();Gerekirse img src'nin sonuna a eklenerek bu önlenebilir .
Meshaal

2
Bu benim için çalışmıyor, Ping isteğinde bilinen kötü bir ana bilgisayar adı ana bilgisayar bulunamadı .... ama hata 'iyi' olduğu için bu şey cevap verdiğini söylüyor
Maslow

5
Daha fazla test bunun tamamen güvenilir olmadığını ortaya koydu.
Leo

2
@Jonathon tarafından oluşturulan Ping API'sı her şeye başarıyla ping atacaktır. Mevcut olmayan siteler ve rastgele karakterler.
IE5Master

2
Ping API'si aslında her zaman hata ile başarısız olur. ANCAK hedef URL bir resmi gösteriyorsa, bu harika bir yükleme yapar! CORS kontrollerini atlar.
Martin Vysny

20

Ping ICMP'dir, ancak uzak sunucuda açık bir TCP bağlantı noktası varsa, şu şekilde elde edilebilir:

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
  }

}


Bu zor çözümü seviyorum. Bir sayı döndürmek yerine pong için bir işlev sağlamak zorunda kalmak benim için biraz garip ama uygulanabilir.
Nick

@armen: ping () işlevine üçüncü argüman olarak bir işlev sağlamalısınız, bu argümanın değerine işlev içinde pong denir.
finitud

2
ping("example.com", "77", function(m){ console.log("It took "+m+" miliseconds."); })..... örnek çağrı
jave.web

@Nick: Bu eşzamansız şeyler, bu nedenle yöntem geri döndüğünde onreadystatechangehenüz tetiklenmedi. Bu, durum değiştiğinde almak için bir geri aramaya ihtiyacınız olduğu anlamına gelir.
huşu

Ev sahibi için ne seçersem, pong () denir. ping ( test.zzzzzzzzz, "77", işlev (m) {console.log ("" + m + "milisaniye aldı.");}) "67 milisaniye aldı" yazdırır. ping ( stackoverflow.com, "80", function (m) {console.log ("" m + "milisaniye aldı.");}) CORS Hatası veriyor: developer.mozilla.org/tr-TR/docs/Web/ HTTP / CORS / Hatalar /… Uzak bir bilgisayar çevrimiçiyse bu kodu nasıl kontrol edebileceğimi göremiyorum.
Tux

18

bunu deneyebilirsiniz:

ping.html dosyasını herhangi bir içerik içeren veya içermeyen sunucuya koyun , javascript'te aşağıdaki ile aynı işlemi yapın:

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

1
Ping yaptığım sunucular benim değil, bu yüzden bu seçeneğim yok. Yine de teşekkürler.
Chuck Callebs

9
@dlchambers CORS için Aidat Değil, ancak etki alanı poilicy DUE TO. CORS, sunucunun orijinlerini belirtmesine izin verir, ayrıca tarayıcı tarafından desteklenmesi gerekir. daha çok siteler arası bir soruna benzer.
Royi Namir

HEAD türü istekleri CORS nedeniyle de çalışmaz. Chromium 55 ile test edildi. Örneğin net :: CONNECTION_REFUSED örneğinde olduğu gibi http kodu 0 ile aynı hatayı alma.
Martin Vysny

Bu daha sıkı bir şekilde çapraz tarayıcıdır.
Gabriel

14

Javascript içinde doğrudan "ping" yapamazsınız. Başka birkaç yol olabilir:

  • ajax
  • İsReachable ile bir java uygulaması kullanma
  • Ping yapan bir sunucu tarafı komut dosyası yazma ve sunucu yazınızla iletişim kurmak için AJAX kullanma
  • Flash'ta ping işlemi de yapabilirsiniz (actionscript)

1
Java'nın isReachable oldukça güvenilmez .... Ama iyi 2018 ve Java Applets zaten modası geçmiş.
dreua

8

Tarayıcı Javascript'te normal ping yapamazsınız, ancak uzak sunucunun bir görüntüsünü yükleyerek uzak sunucunun hayatta olup olmadığını öğrenebilirsiniz. Yükleme başarısız olursa -> sunucu çalışmıyor.

Yükleme süresini olayı kullanarak da hesaplayabilirsiniz. İşte onload olayının nasıl kullanılacağına dair bir örnek .


4
Bu konuda talihsiz şey pinging sunucular web sunucuları değil. Bunlar oyun sunucusu.
Chuck Callebs

1
Sonra sunucu tarafında ping işlemi yapmak zorundasınız - ya da hafif bir http sunucusu düşünebilirsiniz.
Epeli

Agrega ping yapmanın bir yolunu biliyor musunuz? Bu benim ana yavaşlamam, bir isteğin diğeri başlamadan bitmesini bekliyor.
Chuck Callebs

Sunuculara aynı anda ping atmanız gerekir. Bunu select, thread veya süreçlerle başarabilirsiniz. Gerçekten hardcore bir çözüm için Eventmachine'i kullanabilirsiniz.
Epeli

1
Komut satırı pingkomutundan yararlanmayı düşünebilirsiniz . Endüstriyel güç. Ya da, bir ana bilgisayarın çalışıp çalışmadığını izlemek için çeşitli kalp atışı kontrolleri türlerini izlemek için her türlü ücretsiz / açık kaynaklı uygulama vardır.
Tin Man

7

Bir websocket çözümü ile devreye girme ...

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();Çağrı, onopenolay işleyicide olmamalı mı ? :)
jave.web

1
Websocket protokolünü kullanır , ancak aslında bir bağlantı bekleyen bir websocket sunucusu olmadığını varsayar . Bu sadece 'herhangi bir eski IP'ye ping atmak içindir.
Antony Woods

Ancak WebSocket'in desteklenmediğini veya gerçekten bir hata olup olmadığını nasıl tespit edebilirsiniz? :)
jave.web

80 numaralı bağlantı noktasında bir websocket bağlantısını kabul edebilecek bir IP'ye ping atmak için yeterince şanssız olacağınızı düşünüyorsanız , evet, bu geri aramaya da eklemelisiniz isUp();. Veya belirgin bir şekilde websocket-y olmayan bir bağlantı noktası ekleyerek bunu hafifletin.
Antony Woods

Buraya oy verdim, çünkü buraya websocket sunucum yeniden başlatıldığında ne olduğuna bir çözüm aramaya geldim ve bu cevap bana soketin hata işleyicisinde setTimeout'u ve yeniden bağlanmayı denediğimi gösterdi (meşgul bekleme). Muhtemelen en iyi uygulama değil, ama sorunumu çözdü. :)
mynameisnafe

6

İsteklerinizi hızlı tutmak için, ping'in sunucu tarafı sonuçlarını önbelleğe alın ve ping dosyasını veya veritabanını her birkaç dakikada bir güncelleyin (veya olmasını istediğiniz doğru). 8 ping ile bir kabuk komutu çalıştırmak ve çıktıyı bir dosyaya yazmak için cron'u kullanabilirsiniz, web sunucusu bu dosyayı görünümünüze dahil edecektir.


Bunun doğru sonuç için mümkün olan en iyi yol olduğunu düşünüyorum. Ancak yine de sunucu üzerinde bazı çalışmalar gerektirdiğinden akıllı bir yol olmadığını söyleyebilirim.
Chetabahana

5

Görmeye çalıştığınız şey sunucunun "var olup olmadığı" ise, aşağıdakileri kullanabilirsiniz:

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

Bu, sunucunun var olup olmadığı doğru / yanlış göstergesi döndürür.

Yanıt süresi istiyorsanız, küçük bir değişiklik yapılacaktır:

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

Bu durumda kullanım önemsizdir:

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

Veya:

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

Bu bağlantı soruyu cevaplayabilse de, cevabın temel kısımlarını buraya eklemek ve bağlantıyı referans olarak sağlamak daha iyidir. Bağlantı verilen sayfa değişirse, yalnızca bağlantı yanıtları geçersiz olabilir.
vonbrand

1
Bu harika bir çözüm, ancak maalesef yahoo domain sorgu hizmeti değişken sonuçlar veriyor gibi görünüyor. örneğin, aşağıdaki URL'leri denerseniz, start-download .com beginfreedownload .com kayıtlı değil olarak geri gelirler, ancak bu URL'lere giderseniz bunlar açıkça kaydedilir. burada neler olduğu hakkında bir fikrin var mı? (Bu örneklerde alan adlarına bir boşluk ekledim, sadece google suyu vermekten kaçınmak için.
testimde

Yahoo! API, makinenizden bir istek yaparsanız ping bile aynı olmaz. Bu hiç mantıklı değil
Andre Figueiredo

Bu nedenler No 'Access-Control-Allow-Origin' header is present on the requested resource. Originve başarı geri çağırma asla çağrılmaz
vladkras


4

Burada ve özellikle CORS ile ilgili birçok çılgın cevap var -

Bir http HEAD isteği yapabilirsiniz (GET gibi ancak yüksüz). Görmek Https://ochronus.com/http-head-request-good-uses/

Ön kontrol gerektirmez, karışıklık şartnamenin eski bir sürümü nedeniyle, bkz. Neden bir çapraz menşe HEAD isteği ihtiyacı Ön kontrol yapar?

Yani jQuery kütüphanesini kullanan yukarıdaki cevabı kullanabilirsiniz (söylemedi) ama ile

type: 'HEAD'

--->

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

Tabii ki vanilya js veya dojo ya da her neyse kullanabilirsiniz ...


1
HEAD isteği hala "XMLHttpRequest IP yükleyemiyor." Yani CORS tarafından engellendi. Http durumu 0 ile başarı elde edersiniz ve böylece bunu net :: ERR_CONNECTION_REFUSED'den ayırt edemezsiniz
Martin Vysny

0

Hangi Ruby sürümünü kullandığınızı bilmiyorum, ama javascript yerine ruby ​​için ping uygulamayı denediniz mi? http://raa.ruby-lang.org/project/net-ping/


Evet, denedim ama web sunucusundan bağımsız olarak pingler her zaman yanlış geldi. Sadece ping server.comsözdizimini kullanmak için değiştirdim .
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)
});;

bu düğümü ile çalıştırırsanız, google kapalı olmadığı sürece günlük 200'ü konsollayacaktır.


hayır, değil ... 1) eksik gerekiyor, 2) geri dönüyor 301 Kalıcı olarak taşındı: 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);
    }
  });
};

şöyle kullanın:

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

-4

DOS ping.exe komutunu javaScript'ten şu şekilde çalıştırabilirsiniz:

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

İstenen bu mu yoksa bir şey mi kaçırıyorum?


4
Bu maalesef sadece IE üzerinde ve sadece bir Windows Server üzerinde çalışacaktır. Sunucu tarafı komut dosyası çalıştırmak için AJAX kullanmak daha iyi bir seçenek olabilir.
Andrew Grothe

Ne halt? Active X nesneleri kullanıcının dosya sisteminde (win sunucusundaki IE'de) çalıştırılabilir mi? ActiveX ile çalışmamıştım ama bunu hayal etmedim ...
Julix

-6

sadece değiştir

file_get_contents

ile

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

1
Yeni 'kısmi' cevap eklemek yerine önceki cevabınızı düzenlemelisiniz .
Artemix

-8

Bunlardan çok daha kolay olabilir. Sayfanızın yüklenmesini istiyorsanız, başka bir web sayfası etkinliğini tetiklemek için bazı yabancı sayfaların kullanılabilirliğini veya içeriğini kontrol edin, bunu yalnızca javascript ve php kullanarak yapabilirsiniz.

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>

Bunu yapmalı.

Tetiklenen javascript clearInterval (stopmelater) içermelidir

Senin işine yarar mı bileyim

Jerry


2
Daha önce söylediğim gibi, bunlar ping yaptığım web sunucuları değil. Bunlar oyun sunucuları. HTTP isteklerine yanıt vermezler. :(
Chuck Callebs

ahbap, sadece file_get_contents ile değiştir
Jerry Wickey

$ ip = $ _SERVER ['127.0.0.1']; exec ("ping -n 4 $ ip 2> & 1", $ çıktı, $ retval); eğer ($ retval! = 0) {echo "no!"; } başka {echo "yes!"; }
Jerry Wickey

4
Bu bir PHP sorusu değil. Bu bir JavaScript sorusudur. PHP kullanmıyorum.
Chuck Callebs

1
Lütfen yayınlarınızda imza veya etiket satırı kullanmayın, aksi takdirde bunlar kaldırılır. Ayrıntılar için SSS bölümüne bakın .
Artemix

-13

Web sayfanızda PHP kullanmayı deneyebilirsiniz ... şöyle bir şey:

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

?>

Bu test edilmemiştir, bu yüzden yazım hataları vb. Olabilir ... ama işe yarayacağından eminim. Çok geliştirilebilir ...


5
OP'nin etiketlerine göre bu aslında bir Ruby on Rails sorusudur, bu yüzden PHP kullanmak iyi bir çözüm değildir.
Tin Man

1
Burada bir tartışma başlatmak için değil, bu forumun amacı yardımcı değil mi?
Chris

5
@Chris Öyle, ama PHP'ye kod vererek Ruby ve JS'yi uygulayan OP'ye ne tür bir yardım verdiniz?
biphobe
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.