Как определить задержку удаленного сервера через браузер - PullRequest
13 голосов
/ 02 февраля 2009

Я запускаю несколько игровых серверов туннелирования и хотел бы, чтобы у меня была страница, на которой клиент мог бы запустить пинг на всех серверах и выяснить, какой из них наиболее отзывчивый. Насколько я понимаю, кажется, что в JavaScript нет правильного способа сделать это, но я подумал, может кто-нибудь знает, как это сделать во флэш-памяти или какой-нибудь другой технологии клиентского браузера, может быть?

Ответы [ 9 ]

17 голосов
/ 18 февраля 2009

Большинство технологий апплетов, включая 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.
  • Это интенсивная полоса пропускания по сравнению с обычным пингом. Сделайте изображение крошечным, например, файл spacer.gif.
  • Время зависит не только от задержки удаленного сервера, но и от пропускной способности этого сервера. Это может быть более или менее полезной мерой, но важно отметить, что это не просто задержка.
  • Вы должны иметь возможность обслуживать HTTP-запросы от различных серверов, и, что особенно важно, каждый сервер должен обслуживать один и тот же ресурс (или ресурс одинаковой длины). Условия на сервере могут повлиять на время ответа, например, если один сервер сжимает данные, а другой - нет.
8 голосов
/ 22 февраля 2009

Перед вызовом на сервер запишите время 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();

Ваш пинг в миллисекундах:

var ping = endTime. getTime() - startTime.getTime();
6 голосов
/ 22 февраля 2009

Все, что вам действительно нужно, это время от начала соединения до момента первого изменения состояния готовности ...

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 голосов
/ 25 февраля 2009

Имейте в виду, что задержка будет как минимум вдвое больше, чем вы бы увидели для ping, если в итоге вы сделаете запрос TCP для измерения задержки, потому что вам понадобится трехстороннее рукопожатие и пакет завершения как минимум (две поездки туда и обратно, а не одна). Если вы делаете HTTP-запросы, постарайтесь свести заголовки к минимуму. Достаточно длинный заголовок (из-за болтливого сервера, файлов cookie и т. Д. На клиенте) может добавить дополнительные циклы, добавляя ваши измерения.

3 голосов
/ 24 февраля 2009

Вот подход <iframe>:


(источник: magnetiq.com )

Создать таблицу (не обязательно в буквальном смысле <table>) с двумя столбцами. Первый столбец будет содержать имена серверов (и, возможно, ссылки на них). Во втором столбце есть фреймы, загружающие тестовые документы с соответствующих серверов. Каждый пробный документ делает это при первоначальном запросе выборки:

  1. Получить текущее системное время
  2. Выполнить перенаправление (302) на второй пробный документ, передав системное время в качестве параметра запроса
  3. Второй тестовый документ считывает текущее системное время, вычисляет дельту из начального значения, которое было передано ему, и просто отображает его большими жирными буквами. Эта дельта будет временем, которое требуется серверу, чтобы ответить клиенту с помощью ответа на перенаправление, плюс временем, которое требуется клиенту для повторного запроса к цели перенаправления. Это не совсем «пинг», но это сопоставимая мера относительной задержки клиента для каждого сервера. Фактически это «обратный пинг» с сервера на клиент.

Вы бы использовали iframe, не нарушая политику того же домена, потому что нет никакой попытки манипулировать содержимым iframe вообще. Игрок просто увидит значения своими глазами, и вы будете полагаться на то, что пользователь посмотрит на цифры и нажмет на ссылку на сервер, которая наиболее логична.

2 голосов
/ 22 февраля 2009

Нетрудно измерить время отклика сервера во Flash.

Flash должен запросить файл политики перед доступом к удаленным серверам. Расположение по умолчанию для такого файла политики находится в корневой папке сервера: /crossdomain.xml

(Вы можете легко найти информацию о формате междоменного файла)

Так как такой файл нужен в любом случае, почему бы не использовать его для измерения времени отклика сервера? Загрузите сам файл вместо изображения и измерьте время, которое потребовалось с помощью getTimer ().

Это даст вам хорошую оценку HTTP-соединений.

Но если вы имеете дело с игровыми серверами, вы можете напрямую проверить скорость TCP-соединения. Для этого вам нужно использовать flash.net.Socket Вы также должны сначала запросить файл политики, запустив: Security.loadPolicyFile ( "XMLSocket: //server.domain.com: 5342");

Где 5342 представляет номер порта вашего сервера, на который он должен ответить правильной строкой политики XML. После подключения через сокет любой запрос / ответ позволит вам измерить разное время ответа сервера.

2 голосов
/ 02 февраля 2009

Если вы говорите о запуске чего-либо на стороне клиента, я не уверен, что это возможно по соображениям безопасности.

Возможно, лучшим вариантом будет java-апплет, но опять же, это нужно проверить в соответствии с локальной политикой безопасности.

Если я попытаюсь подумать о каком-то хаке в JS, чтобы сделать это, возможно, вы можете попытаться отправить асинхронный запрос с помощью функции обратного вызова, которая измеряет миллисекунды, которые потребовались, - но это не в моей голове. *

1 голос
/ 21 февраля 2009

Проблема с «эхо-запросами файлов» заключается в том, что вы будете оценивать ответ http-сервера, в то время как ваш целевой ресурс для игр, которые вы обслуживаете, может иметь совсем другое поведение и, следовательно, другую задержку.

Просто идея на ровном месте, может быть, даже нереальная в зависимости от реального контекста: но не было бы интересно сделать серверный сценарий на основе короткой последовательности задач, обычно выполняемых серверами во время игры (например, открытие соединения RTMP, получение информации, отправка ее обратно). В зависимости от общего количества серверов вы можете почти одновременно открыть их и определить первый ответ как победителя (вычитая время, которое ваш клиент требует независимо для обработки каждого запроса).

Конечно, это довольно дорогой метод на стороне сервера, но, по крайней мере, вы получите надежный результат (сумма задержек сервера и сети суммируется). Даже если для оценки потребуется пара секунд, это будет делом доли от общего приятного игрового процесса.

0 голосов
/ 29 марта 2019

На основании ответов @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();

Следующий спет помещает источник в изображение. .Src отражает атрибут src html. Важный! Направьте ваш img.src на очень маленький и легкий файл изображения, если это возможно, размером менее 10 КБ.

Для предотвращения кеширования случайный параметр был добавлен в конец файла после расширения .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 получает начальное время минус последнее время. Во всплывающем окне с предупреждением отображается результат.

...