[英]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;
}
然后等待適當的時間並檢查每個服務器對象的時間。 根據需要重復並計算平均值。 我不確定您可以期待什么樣的准確性。
缺點:
在調用服務器之前,記錄 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。 每個探測文檔在初始獲取請求上執行此操作:
您將在不違反同域策略的情況下使用 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.