簡體   English   中英

如何通過瀏覽器確定遠程服務器的延遲

[英]How to determine latency of a remote server through the browser

我運行了幾個游戲隧道服務器,並希望有一個頁面,客戶端可以在其中對所有服務器運行 ping 並找出響應最快的服務器。 據我所知,在 JavaScript 中似乎沒有正確的方法可以做到這一點,但我在想,有沒有人知道一種在 Flash 或其他一些客戶端瀏覽器技術中做到這一點的方法?

大多數小程序技術,包括 Javascript,都強制執行同源策略。 可以使用 onload 事件處理程序動態添加 DOM 元素(例如圖像)並收集時間信息。

偽代碼

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 請求提供服務,而且至關重要的是,每個服務器都應該提供完全相同的資源(或相同長度的資源)。 服務器上的條件會影響響應時間,例如一台服務器是否正在壓縮數據,而另一台則不是。

在調用服務器之前,記錄 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();

您真正需要的是從連接開始到第一次就緒狀態更改的時間......

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.");
}

這是一個<iframe>方法:


(來源: magnetiq.com

創建一個包含兩列的表(不一定是文字<table>意義上的)。 第一列將保存服務器的名稱(可能還有指向它們的鏈接)。 第二列包含從相應服務器加載探測文檔的 iframe。 每個探測文檔在初始獲取請求上執行此操作:

  1. 獲取當前系統時間
  2. 將系統時間作為查詢參數傳遞時,重定向 (302) 到第二個探測文檔
  3. 第二個探測文檔讀取當前系統時間,根據傳遞給它的初始讀數計算增量,並僅以大字體顯示。 此增量將是服務器使用重定向響應響應客戶端所花費的時間加上客戶端向重定向目標發出第二個請求所花費的時間。 它不完全是“ping”,但它是客戶端與每個服務器的相對延遲的可比較度量。 實際上,它是從服務器到客戶端的“反向 ping”。

您將在不違反同域策略的情況下使用 iframe,因為根本沒有嘗試操縱 iframe 內容。 玩家將簡單地用他/她自己的眼睛看到這些值,而您將依賴於用戶瀏覽數字並單擊最有意義的服務器鏈接。

任何發出 HTTP 請求的東西(就像這里的大多數答案一樣)通常會測量延遲,該延遲至少是正常 ping 的兩倍,因為您至少需要三向握手和終止數據包(兩次往返而不是一次)。 如果您發出 HTTP 請求,請盡量減少標頭。 足夠長的標頭(由於聊天服務器或客戶端上的 cookie 等)可以在混合中添加額外的往返行程,從而放棄您的測量。

正如 Cherona 指出的那樣,如果您已經與服務器建立了活動的 HTTP 2 連接,或者如果服務器使用 HTTP 3,則情況可能並非如此。

最准確的選擇是打開到每個服務器的 websocket 連接,並測量發送一條小消息和接收一條小響應所需的時間(在建立連接之后)。

如果您正在談論在客戶端運行某些東西,由於安全原因,我不確定這是否可行。

也許您最好的選擇是 Java 小程序 - 但同樣需要根據本地安全策略進行檢查。

如果我嘗試在 JS 中考慮一些 hack 來做到這一點,也許您可​​以嘗試發送一個帶有回調函數的異步請求,該函數測量它花費的毫秒數 - 但這只是我的想法。

在 Flash 中測量服務器響應時間並不難。

Flash 在訪問遠程服務器之前必須要求提供策略文件。 此類策略文件的默認位置位於服務器的根文件夾中:/crossdomain.xml

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

既然無論如何都需要這樣的文件,為什么不使用它來衡量服務器響應時間呢? 加載文件本身而不是圖像,並使用 getTimer() 測量它花費的時間。

這將為您提供對 HTTP 連接的一個很好的估計。

但是如果您正在處理游戲服務器,您可能需要直接檢查 TCP 連接的速度。 為此,您需要使用 flash.net.Socket 您還必須首先通過運行來請求策略文件: Security.loadPolicyFile("xmlsocket://server.domain.com:5342");

其中 5342 代表您的服務器的端口號,它應該以正確的 XML 策略字符串響應。 建立套接字連接后,任何請求/響應都可以讓您測量不同的服務器響應時間。

根據@Mr. 的回復。 Shiny 和 @Georg Schölly ,一個完整的和評論的例子。

為了進行測試,只需將以下代碼按相同順序復制並粘貼到空的 .html、.php 或其他兼容文件中。

在開始get之前,記錄下當前的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 變量接收初始時間減去最終時間。 警報彈出窗口顯示結果。

“文件 ping”的問題在於您將評估 http 服務器響應,而您所服務的游戲的目標資源可能具有非常不同的行為,從而導致不同的延遲。

只是一個突然的想法,根據實際情況甚至可能不切實際:但是,根據服務器在游戲過程中通常執行的短任務序列(例如打開 RTMP)來制作服務器腳本不是很有趣嗎?連接,檢索信息,將其發回)。 根據服務器的總數,您幾乎可以同時打開它們並將第一個響應定義為獲勝者(減去您的客戶端獨立處理每個查詢所需的時間)。

當然,就服務器端而言,這是一種非常昂貴的方法,但至少您希望得到可靠的結果(服務器和網絡延遲總和)。 即使需要幾秒鍾的時間來評估,這也只是整個愉快游戲的一小部分。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM