如何通过浏览器确定远程服务器的延迟

时间:2009-02-02 13:25:22

标签: javascript flash browser latency ping

我运行了几个游戏隧道服务器,并希望有一个页面,客户端可以在所有服务器上运行ping,并找出响应最快的服务器。据我所知,似乎没有正确的方法在JavaScript中执行此操作,但我在想,是否有人知道在Flash或其他一些客户端浏览器技术中执行此操作的方法?

9 个答案:

答案 0 :(得分:17)

大多数applet技术(包括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;
}

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

缺点:

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

答案 1 :(得分:8)

在调用服务器之前,记录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();

答案 2 :(得分:6)

您真正需要的是从连接开始到第一次状态变更的时间......

function getPing() {
  var start;
  var client = getClient(); // xmlhttprequest object
  client.onreadystatechange = function() {
    if (client.readyState > 0) {
      pingDone(start); //handle ping
      client.onreadystatechange = null; //remove handler
    } 
  }

  start = new Date();
  client.open("HEAD", "/ping.txt"); //static file
  client.send();
}

function pingDone(start) {
  done = new Date();
  ms = done.valueOf() - start.valueOf();
  alert(ms + "ms ping time");
}

function getClient() {
  if (window.XMLHttpRequest)
    return new XMLHttpRequest();

  if (window.ActiveXObject)
    return new ActiveXObject('MSXML2.XMLHTTP.3.0');

  throw("No XMLHttpRequest Object Available.");
}

答案 3 :(得分:3)

这是<iframe>方法:


(来源:magnetiq.com

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

  1. 获取当前系统时间
  2. 在将系统时间作为查询参数传递时,将重定向(302)重定向到第二个探测文档
  3. 第二个探测文档读取当前系统时间,根据传递给它的初始读数计算增量,并以大胖字母显示。此增量将是服务器使用重定向响应加上客户端向重定向目标发出第二个请求所花费的时间来响应客户端所花费的时间。它不完全是“ping”,但它是客户端与每台服务器的相对延迟的可比较度量。实际上,它是从服务器到客户端的“反向ping”。
  4. 您将使用iframe而不会侵犯相同的域政策,因为根本没有尝试操纵iframe内容。玩家只需用他/她自己的眼睛看到这些值,你就会依赖用户浏览数字并点击最有意义的服务器链接。

答案 4 :(得分:3)

请记住,如果您最终使用TCP查询来测量延迟,则延迟将至少是ping的两倍,因为您需要三次握手和终止数据包至少(两次往返而不是一次)。如果您发出HTTP请求,请尝试将标头保持在最低限度。足够长的标题(由于服务器繁忙,或客户端上的cookie等)可以在混合中添加额外的往返行程,从而丢失测量结果。

答案 5 :(得分:2)

如果你在谈论运行某些客户端,我不确定这是否可能由于安全原因。

也许你最好的选择是一个java applet - 但是这需要根据本地安全策略进行检查。

如果我试着考虑JS中的一些黑客来做这件事,也许你可以尝试发送一个带有回调函数的异步请求来测量它所用的毫秒数 - 但这只是我的头脑。

答案 6 :(得分:2)

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

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

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

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

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

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

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

答案 7 :(得分:1)

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

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

当然,这是一种非常昂贵的服务器端方法,但至少可以获得可靠的结果(服务器和网络延迟总结)。即使需要几秒钟的时间来评估,这也只是整个游戏玩法的一小部分。

答案 8 :(得分:0)

基于@Mr的响应。 Shiny和@GeorgSchölly,一个完整且受评论的示例。

要进行测试,只需将以下代码以相同的顺序复制并粘贴到一个空的.html,.php或其他兼容文件中即可。

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

<script type="text/javascript">

var startTime = new Date();

现在让我们创建一个仍然没有源代码的html对象图像,并将其归因于变量img。

var img = new Image();

下一个Spet将在图像中放置一个源。 .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变量接收的是初始时间减去最终时间。 警报弹出窗口显示结果。