Pinging несколько серверов, чтобы определить лучший, чтобы подключиться к [duplicate]

Когда ваши пути include разные

Ошибки компоновщика могут произойти, если заголовочный файл и связанная с ним общая библиотека (файл .lib) не синхронизируются. Позволь мне объяснить.

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

Возможно ли получить ошибку компоновщика, даже если объявление и определение, похоже, совпадают? Да! Они могут выглядеть одинаково в исходном коде, но это действительно зависит от того, что видит компилятор. По сути, вы можете столкнуться с такой ситуацией:

// header1.h
typedef int Number;
void foo(Number);

// header2.h
typedef float Number;
void foo(Number); // this only looks the same lexically

Обратите внимание, что хотя обе декларации функций выглядят одинаково в исходном коде, но они действительно различаются в зависимости от компилятора.

Вы можете спросить, как это получается в такой ситуации? Включите пути, конечно! Если при компиляции разделяемой библиотеки путь include приводит к header1.h, и вы в конечном итоге используете header2.h в своей собственной программе, вы оставите царапины на своем заголовке, задаваясь вопросом, что произошло (каламбур).

Пример того, как это может произойти в реальном мире, объясняется ниже.

Дальнейшая разработка с примером

У меня есть два проекта: graphics.lib и main.exe. Оба проекта зависят от common_math.h. Предположим, что библиотека экспортирует следующую функцию:

// graphics.lib    
#include "common_math.h" 

void draw(vec3 p) { ... } // vec3 comes from common_math.h

И затем вы идете вперед и включаете библиотеку в свой собственный проект.

// main.exe
#include "other/common_math.h"
#include "graphics.h"

int main() {
    draw(...);
}

Boom! Вы получаете ошибку компоновщика, и вы понятия не имеете, почему она терпит неудачу. Причина в том, что общая библиотека использует разные версии одного и того же include common_math.h (я сделал это очевидным здесь в этом примере, включив другой путь, но это может быть не всегда так очевидно. Возможно, путь include отличается в настройки компилятора).

Обратите внимание, что в этом примере компоновщик сказал бы вам, что не смог найти draw(), когда на самом деле вы знаете, что он явно экспортируется библиотекой. Вы могли часами царапать себе голову, думая, что пошло не так. Дело в том, что компоновщик видит другую подпись, потому что типы параметров немного отличаются. В этом примере vec3 является другим типом в обоих проектах в отношении компилятора. Это может произойти из-за того, что они происходят из двух немного разных файлов include (возможно, включенные файлы поступают из двух разных версий библиотеки).

Отладка компоновщика

DUMPBIN - ваш друг, если вы используете Visual Studio. Я уверен, что другие компиляторы имеют другие подобные инструменты.

Процесс выглядит следующим образом:

  1. Обратите внимание на странное искаженное имя, указанное в ошибке компоновщика. (например, draw @ graphics @ XYZ).
  2. Выгрузите экспортированные символы из библиотеки в текстовый файл.
  3. Найдите экспортированный символ, представляющий интерес, и обратите внимание, что искаженное имя
  4. Обратите внимание на то, почему искаженные имена оказались разными. Вы могли бы видеть, что типы параметров различны, хотя они выглядят одинаково в исходном коде.
  5. Причина, почему они разные. В приведенном выше примере они различаются из-за разных файлов include.

[1] По проекту я имею в виду набор исходных файлов, которые связаны друг с другом для создания либо библиотеки, либо исполняемого файла .

РЕДАКТИРОВАТЬ 1: Переписать первый раздел, который будет легче понять. Пожалуйста, прокомментируйте ниже, чтобы сообщить мне, нужно ли что-то еще исправлять. Спасибо!

121
задан Grant Thomas 9 September 2013 в 13:56
поделиться

14 ответов

Я нашел человека, который выполняет это с очень умным использованием собственного Image объекта.

Из их источника это основная функция (она имеет зависимости от других частей источника, но вы получаете идею).

function Pinger_ping(ip, callback) {

  if(!this.inUse) {

    this.inUse = true;
    this.callback = callback
    this.ip = ip;

    var _that = this;

    this.img = new Image();

    this.img.onload = function() {_that.good();};
    this.img.onerror = function() {_that.good();};

    this.start = new Date().getTime();
    this.img.src = "http://" + ip;
    this.timer = setTimeout(function() { _that.bad();}, 1500);

  }
}

Это работает на всех типах серверов которые я тестировал (веб-серверы, ftp-серверы и игровые серверы). Он также работает с портами. Если кто-либо встречает случай использования, который терпит неудачу, напишите в комментариях, и я обновлю свой ответ.

Обновление: ссылка была удалена. Если кто-либо находит или реализует вышеизложенное, прокомментируйте, и я добавлю его в ответ.

Обновление 2: @trante было достаточно приятно, чтобы предоставить jsFiddle.

http://jsfiddle.net/GSSCD/203/

Обновление 3: @Jonathon создал репозиторий GitHub с реализацией.

https://github.com/jdfreder/pingjs

Обновление 4: похоже, что эта реализация более не является надежной. Люди также сообщают, что Chrome больше не поддерживает все это, выбросив ошибку net::ERR_NAME_NOT_RESOLVED. Если кто-то может проверить альтернативное решение, я поставлю это как принятый ответ.

114
ответ дан Chuck Callebs 28 August 2018 в 01:23
поделиться

Прыгание с помощью решения для веб-рассылки ...

function ping(ip, isUp, isDown) {
  var ws = new WebSocket("ws://" + ip);
  ws.onerror = function(e){
    isUp();
    ws = null;
  };
  setTimeout(function() { 
    if(ws != null) {
      ws.close();
      ws = null;
      isDown();
    }
  },2000);
}
5
ответ дан acron 28 August 2018 в 01:23
поделиться

Вы можете попробовать использовать PHP на своей веб-странице ... что-то вроде этого:

<html><body>
<form method="post" name="pingform" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<h1>Host to ping:</h1>
<input type="text" name="tgt_host" value='<?php echo $_POST['tgt_host']; ?>'><br>
<input type="submit" name="submit" value="Submit" >
</form></body>
</html>
<?php

$tgt_host = $_POST['tgt_host'];
$output = shell_exec('ping -c 10 '. $tgt_host.');

echo "<html><body style=\"background-color:#0080c0\">
<script type=\"text/javascript\" language=\"javascript\">alert(\"Ping Results: " . $output . ".\");</script>
</body></html>";

?>

Это не проверено, поэтому у него могут быть опечатки и т. д. ... но я уверен, что это сработает. Также может быть улучшено ...

-12
ответ дан Chris 28 August 2018 в 01:23
поделиться

Здесь много безумных ответов, и особенно о CORS -

. Вы можете выполнить запрос HTTP HEAD (например, GET, но без полезной нагрузки). См. https://ochronus.com/http-head-request-good-uses/

Ему НЕ нужна проверка перед полетом, путаница из-за старой версии спецификация, см. Почему запрос HEAD для перекрестного происхождения нуждается в предварительной проверке?

Итак, вы можете использовать ответ выше, который использует библиотеку jQuery (не сказал этого ), но с

type: 'HEAD'

--->

<script>
    function ping(){
       $.ajax({
          url: 'ping.html',
          type: 'HEAD',
          success: function(result){
             alert('reply');
          },     
          error: function(result){
              alert('timeout/error');
          }
       });
    }
</script>

Вы также можете использовать vanilla js или dojo или что-то еще ...

7
ответ дан Community 28 August 2018 в 01:23
поделиться

Вы не можете напрямую «ping» в javascript. Могут быть несколько других способов:

  • Ajax
  • Использование java-апплета с isReachable
  • Написание скрипта на сервере который пингует и использует AJAX для связи с вашим serveridescript
  • Возможно, вы также сможете выполнить ping во flash (actionscript)
12
ответ дан Eugene 28 August 2018 в 01:23
поделиться

Вы можете запустить команду DOS ping.exe из javaScript, используя следующую команду:

function ping(ip)
{
    var input = "";
    var WshShell = new ActiveXObject("WScript.Shell");
    var oExec = WshShell.Exec("c:/windows/system32/ping.exe " + ip);

    while (!oExec.StdOut.AtEndOfStream)
    {
            input += oExec.StdOut.ReadLine() + "<br />";
    }
    return input;
}

. Это то, о чем просили, или мне что-то не хватает?

-3
ответ дан garryg 28 August 2018 в 01:23
поделиться

вы можете попробовать:

поместить ping.html на сервер с содержимым или без него, на javascript сделать то же самое, что и ниже:

<script>
    function ping(){
       $.ajax({
          url: 'ping.html',
          success: function(result){
             alert('reply');
          },     
          error: function(result){
              alert('timeout/error');
          }
       });
    }
</script>
16
ответ дан jerjer 28 August 2018 в 01:23
поделиться

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

yourpage.php

<?php
if (isset($_GET['urlget'])){
  if ($_GET['urlget']!=''){
    $foreignpage= file_get_contents('http://www.foreignpage.html');
    // you could also use curl for more fancy internet queries or if http wrappers aren't active in your php.ini
    // parse $foreignpage for data that indicates your page should proceed
    echo $foreignpage; // or a portion of it as you parsed
    exit();  // this is very important  otherwise you'll get the contents of your own page returned back to you on each call
  }
}
?>

<html>
  mypage html content
  ...

<script>
var stopmelater= setInterval("getforeignurl('?urlget=doesntmatter')", 2000);

function getforeignurl(url){
  var handle= browserspec();
  handle.open('GET', url, false);
  handle.send();
  var returnedPageContents= handle.responseText;
  // parse page contents for what your looking and trigger javascript events accordingly.
  // use handle.open('GET', url, true) to allow javascript to continue executing. must provide a callback function to accept the page contents with handle.onreadystatechange()
}
function browserspec(){
  if (window.XMLHttpRequest){
    return new XMLHttpRequest();
  }else{
    return new ActiveXObject("Microsoft.XMLHTTP");
  }
}

</script>

Это должно сделать это.

Запущенный javascript должен включать clearInterval (stopmelater)

Позвольте мне знаете, если это сработает для вас

Jerry

-6
ответ дан Jerry Wickey 28 August 2018 в 01:23
поделиться
let webSite = 'https://google.com/' 
https.get(webSite, function (res) {
    // If you get here, you have a response.
    // If you want, you can check the status code here to verify that it's `200` or some other `2xx`.
    console.log(webSite + ' ' + res.statusCode)
}).on('error', function(e) {
    // Here, an error occurred.  Check `e` for the error.
    console.log(e.code)
});;

, если вы запустили это с помощью узла, он будет пустым журналом 200 до тех пор, пока Google не будет работать.

0
ответ дан LifterCoder 28 August 2018 в 01:23
поделиться

Ping является ICMP, но если на удаленном сервере есть какой-либо открытый TCP-порт, он может быть достигнут следующим образом:

function ping(host, port, pong) {

  var started = new Date().getTime();

  var http = new XMLHttpRequest();

  http.open("GET", "http://" + host + ":" + port, /*async*/true);
  http.onreadystatechange = function() {
    if (http.readyState == 4) {
      var ended = new Date().getTime();

      var milliseconds = ended - started;

      if (pong != null) {
        pong(milliseconds);
      }
    }
  };
  try {
    http.send(null);
  } catch(exception) {
    // this is expected
  }

}

12
ответ дан Nils Holgersson 28 August 2018 в 01:23
поделиться

Проблема со стандартными пингами - это ICMP, которые не допускают многие места для обеспечения безопасности и трафика . Это может объяснить неудачу.

Ruby до 1.9 имел TCP ping.rb, который будет работать с Ruby 1.9+. Все, что вам нужно сделать, это скопировать его с установки 1.8.7 в другое место. Я только что подтвердил, что он будет запускаться путем проверки моего домашнего маршрутизатора.

4
ответ дан the Tin Man 28 August 2018 в 01:23
поделиться

Чтобы быстро выполнять ваши запросы, кешируйте результаты на стороне сервера ping и обновляйте файл или базу ping каждые пару минут (или, насколько это точно, вы хотите, чтобы это было). Вы можете использовать cron для запуска команды оболочки с вашими 8 пинами и записи вывода в файл, веб-сервер будет включать этот файл в ваше представление.

5
ответ дан user456733 28 August 2018 в 01:23
поделиться

Я не знаю, какую версию Ruby вы используете, но попробовали ли вы выполнить ping для ruby ​​вместо javascript? http://raa.ruby-lang.org/project/net-ping/

0
ответ дан wajiw 28 August 2018 в 01:23
поделиться

Если вы пытаетесь увидеть, существует ли сервер «существует», вы можете использовать следующее:

function isValidURL(url) {
    var encodedURL = encodeURIComponent(url);
    var isValid = false;

    $.ajax({
      url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22" + encodedURL + "%22&format=json",
      type: "get",
      async: false,
      dataType: "json",
      success: function(data) {
        isValid = data.query.results != null;
      },
      error: function(){
        isValid = false;
      }
    });

    return isValid;
}

Это вернет значение true / false, существует ли сервер.

Если вам требуется время отклика, будет сделана небольшая модификация:

function ping(url) {
    var encodedURL = encodeURIComponent(url);
    var startDate = new Date();
    var endDate = null;
    $.ajax({
      url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22" + encodedURL + "%22&format=json",
      type: "get",
      async: false,
      dataType: "json",
      success: function(data) {
        if (data.query.results != null) {
            endDate = new Date();
        } else {
            endDate = null;
        }
      },
      error: function(){
        endDate = null;
      }
    });

    if (endDate == null) {
        throw "Not responsive...";
    }

    return endDate.getTime() - startDate.getTime();
}

Использование тогда тривиально:

var isValid = isValidURL("http://example.com");
alert(isValid ? "Valid URL!!!" : "Damn...");

Или:

var responseInMillis = ping("example.com");
alert(responseInMillis);
4
ответ дан Yasir Arsanukaev 28 August 2018 в 01:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: