【问题标题】:How to determine latency of a remote server through the browser如何通过浏览器确定远程服务器的延迟
【发布时间】:2010-10-04 22:18:43
【问题描述】:

我运行了几个游戏隧道服务器,并希望有一个页面,客户端可以在其中对所有服务器运行 ping 并找出响应最快的服务器。据我所知,在 JavaScript 中似乎没有合适的方法来做到这一点,但我在想,有没有人知道在 flash 或其他客户端浏览器技术中做到这一点的方法?

【问题讨论】:

  • 我对您的解决方案很感兴趣。有机会得到一些结果吗?提前致谢!
  • 对我来说最有趣的答案是 Eliram (stackoverflow.com/questions/503199/…) 的答案,但 StackOverflow 已经为我选择了答案。不过,我还没有进一步说服这个项目。我不是 Flash 开发者

标签: javascript flash browser latency ping


【解决方案1】:

大多数小程序技术(包括 Javascript)都执行同源策略。可以动态添加 DOM 元素,例如图像,并使用 onload 事件处理程序收集时间信息。

伪代码

for (server in servers) {
  var img = document.createElement('IMG');
  server.startTime = getCurrentTimeInMS();
  img.onload=function() { server.endTime = getcurrentTimeInMS(); }
  img.src = server.imgUrl;
}

然后等待适当的时间并检查每个服务器对象的时间。根据需要重复并根据需要计算平均值。我不确定您可以期待什么样的准确度。

缺点:

  • 您可能使用了错误的工具来完成这项工作。没有为此类应用配备浏览器。
  • 这可能非常不准确。
  • 如果您请求的资源被缓存,它不会给您想要的结果,但您可以通过每次更改 url 来解决这个问题。
  • 与普通 ping 相比,这会占用大量带宽。使图像变小,例如 spacer.gif 文件。
  • 时间不仅取决于远程服务器的延迟,还取决于该服务器的带宽。这可能或多或少有用,但重要的是要注意它不仅仅是延迟。
  • 您需要能够为来自不同服务器的 HTTP 请求提供服务,而且至关重要的是,每台服务器都应该提供完全相同的资源(或相同长度的资源)。服务器上的条件会影响响应时间,例如一台服务器正在压缩数据而另一台没有。

【讨论】:

  • 使用 new Image() 而不是创建整个 DOM 对象。
  • @gs: 使用 new Image() 有优势吗?
  • 所有这些解决方案(包括下载内容)的问题在于,它实际上是在测试 Web 服务器的速度,而不是网络连接的延迟。因此,这并不是真正的反映,尤其是对于我对非常具体的网络延迟速度的需求。
  • @Mladen Mihajlovic:这是您使用的技术的限制。大多数小程序技术不允许您与任意服务器建立任意 TCP/UDP 连接。这就是你所需要的。
  • 似乎在 Flash 中是可能的(见下面的答案)。唯一的问题是我根本不知道 flash :)
【解决方案2】:

在调用服务器之前,记录下Javascript时间:

var startTime = new Date();

从服务器加载图像:

var img = new Image()
img.onload = function() {
    // record end time
}
img.src = "http://server1.domain.com/ping.jpg";

请求完成后,再次记录时间。 (当然考虑到请求没有超时。)

var endTime = new Date();

您的 ping 以毫秒为单位:

var ping = endTime. getTime() - startTime.getTime();

【讨论】:

    【解决方案3】:

    您真正需要的只是从连接开始到第一次 readystate 更改的时间...

    函数 getPing() { 变量开始; var 客户端 = getClient(); // xmlhttp请求对象 client.onreadystatechange = function() { if (client.readyState > 0) { pingDone(开始); //处理ping 客户端.onreadystatechange = null; //删除处理程序 } } 开始 = 新日期(); client.open("HEAD", "/ping.txt"); //静态文件 客户端.send(); } 功能 pingDone(开始) { 完成 = 新日期(); ms = done.valueOf() - start.valueOf(); alert(ms + "ms ping 时间"); } 函数 getClient() { 如果(窗口.XMLHttpRequest) 返回新的 XMLHttpRequest(); 如果(窗口。ActiveXObject) 返回新的 ActiveXObject('MSXML2.XMLHTTP.3.0'); throw("没有可用的 XMLHttpRequest 对象。"); }

    【讨论】:

    • 这仅在您 ping 托管网页的服务器时有效,而不适用于 ping 其他服务器。
    【解决方案4】:

    这是<iframe> 方法:


    (来源:magnetiq.com

    创建一个包含两列的表(不一定是字面意义上的<table>)。第一列将包含服务器的名称(可能还有指向它们的链接)。第二列具有从相应服务器加载探测文档的 iframe。每个探测文档都会在初始获取请求中执行此操作:

    1. 获取当前系统时间
    2. 执行重定向 (302) 到第二个探测文档,同时将系统时间作为查询参数传递
    3. 第二个探测文档读取当前系统时间,根据传递给它的初始读数计算增量,并以大字体显示。此增量将是服务器以重定向响应响应客户端所用的时间加上客户端向重定向目标发出第二次请求所用的时间。它不完全是“ping”,但它是客户端与每台服务器的相对延迟的可比较度量。实际上,这是从服务器到客户端的“反向 ping”。

    您在使用 iframe 时不会违反同域政策,因为根本不会尝试操纵 iframe 内容。玩家只会用自己的眼睛看到这些值,而您将依赖于用户查看数字并单击最有意义的服务器链接。

    【讨论】:

      【解决方案5】:

      任何发出 HTTP 请求的东西(就像这里的大多数答案一样)通常测量的延迟至少是正常 ping 的两倍,因为您需要三向握手和终止数据包至少(两次往返而不是一次)。如果您发出 HTTP 请求,请尽量减少标头。足够长的标头(由于聊天服务器或客户端上的 cookie 等)可能会增加额外的往返行程,从而影响您的测量。

      正如 Cherona 指出的那样,如果您已经与服务器建立了活动的 HTTP 2 连接,或者如果服务器使用 HTTP 3,那么情况可能并非如此。

      最准确的选择是打开到每个服务器的 websocket 连接,并测量发送微小消息和接收微小响应所需的时间(在建立连接之后)。

      【讨论】:

      • 这不适用于 HTTP2 和 HTTP3
      • 好点!编辑添加提及 HTTP 2、HTTP 3 和 websockets。
      【解决方案6】:

      如果您说的是在客户端运行某些东西,出于安全原因,我不确定这是否可行。

      也许您最好的选择是使用 java 小程序 - 但同样需要根据本地安全策略进行检查。

      如果我尝试在 JS 中考虑一些 hack 来做到这一点,也许您可​​以尝试发送一个带有回调函数的异步请求,该函数测量它所花费的毫秒数 - 但这只是我的想法。

      【讨论】:

      • 我知道一种方法是发送 HEAD 请求,但我更希望有一种方法可以使用 flash?
      • Java 小程序只允许联系它们的源服务器。
      • 具有更高安全性的小程序如果被签名并被接受,则被允许使用。或者至少他们曾经是。我最后一次看到的是 Netscape 4。
      【解决方案7】:

      在 Flash 中测量服务器响应时间并不难。

      Flash 必须在访问远程服务器之前请求策略文件。 此类策略文件的默认位置是服务器的根文件夹:/crossdomain.xml

      (您可以轻松找到有关跨域文件格式的信息)

      既然需要这样的文件,为什么不使用它来测量服务器响应时间呢?加载文件本身而不是图像,并使用 getTimer() 测量它所花费的时间。

      这将为您提供对 HTTP 连接的良好估计。

      但如果您正在处理游戏服务器,您可能需要直接检查 TCP 连接的速度。为此,您需要使用 flash.net.Socket 您还必须首先通过运行请求策略文件: Security.loadPolicyFile("xmlsocket://server.domain.com:5342");

      其中 5342 表示您的服务器端口号,它应该使用正确的 XML 策略字符串进行响应。 建立套接字连接后,任何请求/响应都会让您测量不同的服务器响应时间。

      【讨论】:

      • 这听起来很有希望。你有一些代码,或者我可以看到的示例闪存“小程序”吗?我自己不是动作脚本程序员。
      【解决方案8】:

      “文件 ping”的问题在于,您将评估 http 服务器响应,而您所服务的游戏的目标资源可能具有非常不同的行为,从而导致不同的延迟。

      只是一个突然的想法,根据实际情况甚至可能不切实际: 但是,基于通常在游戏过程中由服务器执行的短序列任务(例如打开 RTMP 连接、检索信息、将其发回)来制作服务器脚本不是很有趣。根据服务器的总数,您几乎可以同时打开它们并将第一个响应定义为获胜者(减去您的客户端独立处理每个查询所需的时间)。

      当然,从服务器端来说,这是一种相当昂贵的方法,但至少你希望得到一个可靠的结果(服务器和网络延迟的总和)。即使评估需要几秒钟,这也只是整个游戏乐趣的一小部分。

      【讨论】:

        【解决方案9】:

        基于@Mr. 的回复。 Shiny 和 @Georg Schölly ,一个完整的注释示例。

        为了测试,只需将以下代码以相同的顺序复制并粘贴到空的 .html、.php 或其他兼容文件中。

        在开始获取之前,记录当前的Javascript时间。 使用new Date(),我们创建一个具有当前日期和时间的新日期对象。

        <script type="text/javascript">
        
        var startTime = new Date();
        

        现在让我们创建一个 html 对象图像,仍然没有源,并将其属性到变量 img。

        var img = new Image();
        

        下一个例子是在图像中放置一个源。 .src 反映了 src html 属性。 重要的!将您的 img.src 指向一个非常小且轻量级的图像文件,如果可能的话小于 10KB。

        为了防止缓存,在文件末尾添加了一个随机参数,位于 .png 扩展名之后。

        var random_string = Math.random().toString();
        img.src = "http://static.bbci.co.uk/frameworks/barlesque/5.0.0/orb/4/img/bbc-blocks-dark.png" + "?" + random_string;
        

        现在我们可以调用我们的函数,该函数将在图像加载时运行,因为 .onload:

        img.onload = function() {
            var endTime = new Date();
            var ping = endTime. getTime() - startTime.getTime();
            alert(img.src + " loaded in " + ping + " ms");
        }
        </script>
        

        在函数内部,我们有一个变量 endTime,它接收源图像加载后的日期时间。

        最后,ping 变量接收初始时间减去最终时间。 警报弹出窗口会显示结果。

        【讨论】:

          猜你喜欢
          • 2023-04-06
          • 2017-06-15
          • 2015-09-30
          • 2017-02-05
          • 2020-03-27
          • 2015-05-07
          • 2013-04-12
          • 2019-11-11
          • 1970-01-01
          相关资源
          最近更新 更多