如何使用 JavaScript ping IP 地址

IT技术 javascript ping latency
2021-02-24 02:12:43

我想运行一个 JavaScript 代码来 ping 4 个不同的 IP 地址,然后检索这些 ping 请求的丢包和延迟并将它们显示在页面上。

我该怎么做呢?

6个回答

你不能从 JS 中做到这一点。你可以做的是:

 client --AJAX-- yourserver --ICMP ping-- targetservers

向您的服务器发出 AJAX 请求,然后该服务器将为您 ping 目标服务器,并在 AJAX 结果中返回结果。

可能的警告:

  • 这告诉你目标服务器是否可以从你的服务器 ping 通,而不是从用户的客户端
    • 因此客户端将无法测试其 LAN 主机
    • 但是你不应该让主机检查服务器内部网络上的主机,如果有的话
    • 某些主机可能会阻止来自某些主机而不是其他主机的流量
  • 您需要限制每台机器的 ping 计数:
    • 避免 AJAX 请求超时
    • 当您一直 ping 他们的网站时,某些网站运营商可能会非常沮丧
  • 资源
    • 长时间运行的 HTTP 请求可能会遇到服务器的最大连接限制,请检查它有多高
    • 许多试图同时 ping 的用户可能会产生可疑的流量(所有 ICMP 和其他任何内容)
  • 并发 - 您可能希望至少将 up/down 状态池/缓存几秒钟,以便希望 ping 同一个目标的多个客户端不会启动大量 ping

我能想到的唯一方法是从外部服务器加载例如图像文件。当加载失败时,您“知道”服务器没有响应(您实际上不知道,因为服务器可能只是阻止了您)。

看看这个示例代码,看看我的意思:

 /*note that this is not an ICMP ping - but a simple HTTP request
    giving you an idea what you could do . In this simple implementation it has flaws
    as Piskvor correctly points out below */
    function ping(extServer){
     var ImageObject = new Image();
     ImageObject.src = "http://"+extServer+"/URL/to-a-known-image.jpg"; //e.g. logo -- mind the caching, maybe use a dynamic querystring
     if(ImageObject.height>0){
       alert("Ping worked!");
     } else {
       alert("Ping failed :(");
     }

}
这不是 ping,而是 HTTP 请求(因此是 TCP/IP)。此外,如果目标不运行HTTP服务器,该请求将花费过长...时间超时; 另外,加载是异步的 - 除非图像已经在缓存中,如果在设置后立即检查 ImageObject.height 将返回 0 src; 如果它在高速缓存中,它会返回“平安工作”,目标是打开还是不行。en.wikipedia.org/wiki/Ping
2021-05-03 02:12:43
警告:以上将缓存。确保在 URL 末尾附加一些独特的内容。此外,单独的 IP/域也适用于图像src"http://" + ipOrHost + "?pingedat=" + new Date().getTime();
2021-05-04 02:12:43
不要亲自投票,我没有投票给你我只是觉得它并没有真正回答这个问题——尽管它一种检查已知 HTTP 服务器是否可能启动的简单方法,但它并没有真正回答 ping 丢失或延迟。我同意我的方法不是从客户端的计算机 ping,这将需要大量降低的权限和许多安全漏洞(和 ActiveX)。
2021-05-12 02:12:43
不是针对个人 :-) 感谢您的跟进
2021-05-12 02:12:43
放松 Piskvor - 您完全正确,这不是真正的 ping(您的解决方案也不是)-您需要能够打开套接字并发送任意 TCP/IP 数据包来模拟 ping-为了简单起见,我只是将方法称为 ping . 你也是正确的,如果目标不运行 HTTP 服务器,它将需要很长时间 - 因此我写了“已知图像的 URL”......缓存也是一个问题。这是您可以采用的方法简单演示,与 CSS 历史黑客的原理相同。感谢您的反对票。
2021-05-14 02:12:43

我受到了最新评论的启发,所以我写了这段简短的代码。

这是一种“HTTP ping”,我认为与 XMLHttpRequest 调用()一起使用非常有用,例如确定在某些情况下使用哪个服务器最快或从用户的互联网收集一些粗略的统计数据连接速度。

这个小函数只是在不存在的 URL 上连接到 HTTP 服务器(预计会返回 404),然后测量直到服务器响应 HTTP 请求的时间,并对累计时间进行平均和迭代次数。

请求的 URL 在每次调用时都会随机修改,因为我注意到(可能)一些透明代理或缓存机制在某些情况下会导致伪造,从而提供额外的快速答案(实际上比 ICMP 快,这有点奇怪)。

请注意使用适合真实 HTTP 服务器的 FQDN!结果将显示到 ID 为“result”的 body 元素,例如:

<div id="result"></div>

功能代码:

function http_ping(fqdn) {

var NB_ITERATIONS = 4; // number of loop iterations
var MAX_ITERATIONS = 5; // beware: the number of simultaneous XMLHttpRequest is limited by the browser!
var TIME_PERIOD = 1000; // 1000 ms between each ping
var i = 0;
var over_flag = 0;
var time_cumul = 0;
var REQUEST_TIMEOUT = 9000;
var TIMEOUT_ERROR = 0;

document.getElementById('result').innerHTML = "HTTP ping for " + fqdn + "</br>";

var ping_loop = setInterval(function() {


        // let's change non-existent URL each time to avoid possible side effect with web proxy-cache software on the line
        url = "http://" + fqdn + "/a30Fkezt_77" + Math.random().toString(36).substring(7);

        if (i < MAX_ITERATIONS) {

            var ping = new XMLHttpRequest();

            i++;
            ping.seq = i;
            over_flag++;

            ping.date1 = Date.now();

            ping.timeout = REQUEST_TIMEOUT; // it could happen that the request takes a very long time

            ping.onreadystatechange = function() { // the request has returned something, let's log it (starting after the first one)

                if (ping.readyState == 4 && TIMEOUT_ERROR == 0) {

                    over_flag--;

                    if (ping.seq > 1) {
                        delta_time = Date.now() - ping.date1;
                        time_cumul += delta_time;
                        document.getElementById('result').innerHTML += "</br>http_seq=" + (ping.seq-1) + " time=" + delta_time + " ms</br>";
                    }
                }
            }


            ping.ontimeout = function() {
                TIMEOUT_ERROR = 1;
            }

            ping.open("GET", url, true);
            ping.send();

        }

        if ((i > NB_ITERATIONS) && (over_flag < 1)) { // all requests are passed and have returned

            clearInterval(ping_loop);
            var avg_time = Math.round(time_cumul / (i - 1));
            document.getElementById('result').innerHTML += "</br> Average ping latency on " + (i-1) + " iterations: " + avg_time + "ms </br>";

        }

        if (TIMEOUT_ERROR == 1) { // timeout: data cannot be accurate

            clearInterval(ping_loop);
            document.getElementById('result').innerHTML += "<br/> THERE WAS A TIMEOUT ERROR <br/>";
            return;

        }

    }, TIME_PERIOD);
}

例如,启动:

fp = new http_ping("www.linux.com.au"); 

请注意,尽管 HTTP 响应时间似乎与 ICMP 响应时间大致呈指数关系,但我无法在该脚本的结果数字与相应相同服务器上的 ICMP ping 之间找到简单的相关性。这可能是由于通过 HTTP 请求传输的数据量可能会因 Web 服务器的风格和配置而异,显然是服务器本身的速度以及可能的其他原因。

这不是很好的代码,但我认为它可以帮助并可能启发他人。

在 JS 中最接近 ping 的方法是使用 AJAX,并检索就绪状态、状态和标头。像这样的东西:

url = "<whatever you want to ping>"
ping = new XMLHttpRequest();    
ping.onreadystatechange = function(){

    document.body.innerHTML += "</br>" + ping.readyState;

    if(ping.readyState == 4){
        if(ping.status == 200){
            result = ping.getAllResponseHeaders();
            document.body.innerHTML += "</br>" + result + "</br>";
        }
    }

}
ping.open("GET", url, true);    
ping.send();

当然,您也可以为不同的 http 状态设置条件,并根据需要使用描述等显示输出,以使其看起来更好。比 ping 更像是 http url 状态检查器,但实际上是相同的想法。你总是可以循环几次,让它感觉更像是对你的 ping :)

使用 AJAX 和检索就绪状态的想法对我有用。请问如何在此内容中添加 else 语句。就像如果网址不可用,我想向用户打印按摩。像 document.getElementById("div").innerHTML = "Ping 不成功!";
2021-05-19 02:12:43
function ping(url){
 new Image().src=url
}

以上 ping 给定的 Url。
通常用于计数器/分析。
它不会遇到对客户端的失败响应(javascript)

这将检查服务器是否响应请求,例如 http 请求。ping 是完全不同的东西。
2021-04-27 02:12:43
这不会发送 icmp 数据包
2021-05-14 02:12:43