Как я могу пинговать порт сервера с PHP? - PullRequest
40 голосов
/ 23 марта 2012

Мне нужен PHP-скрипт, который позволяет пинговать IP-адрес и номер порта (ip:port).Я нашел похожий скрипт, но он работает только для веб-сайтов, а не ip:port.

<?php

function ping($host, $port, $timeout) 
{ 
  $tB = microtime(true); 
  $fP = fSockOpen($host, $port, $errno, $errstr, $timeout); 
  if (!$fP) { return "down"; } 
  $tA = microtime(true); 
  return round((($tA - $tB) * 1000), 0)." ms"; 
}

//Echoing it will display the ping if the host is up, if not it'll say "down".
echo ping("www.google.com", 80, 10);

?>

Я хочу это для игрового сервера.

Идея состоит в том, что я могу ввести IPадрес и номер порта, и я получаю ответ на пинг.

Ответы [ 9 ]

67 голосов
/ 23 марта 2012

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

Если вы хотите выяснить, примет ли данный хост хостTCP-соединения на порту 80, вы можете сделать это:

$host = '193.33.186.70'; 
$port = 80; 
$waitTimeoutInSeconds = 1; 
if($fp = fsockopen($host,$port,$errCode,$errStr,$waitTimeoutInSeconds)){   
   // It worked 
} else {
   // It didn't work 
} 
fclose($fp);

Для чего-либо кроме TCP это будет сложнее (хотя, так как вы указываете 80, я думаю, вы ищете активный HTTP-сервер, поэтому TCPэто то, что вы хотите).TCP секвенируется и подтверждается, поэтому вы неявно получите возвращенный пакет, когда соединение будет успешно установлено.Большинство других транспортных протоколов (обычно UDP, но также и другие) не ведут себя таким образом, и дейтаграммы не будут подтверждены, пока наложенный протокол уровня приложений не реализует его.

Тот факт, что вы задаете этот вопросэтот способ говорит мне, что у вас есть фундаментальный пробел в ваших знаниях по протоколам Transport Layer .Вы должны прочитать о ICMP и TCP , а также о Модель OSI .

Кроме того, вот чуть более чистая версия для пинга до хостов.

// Function to check response time
function pingDomain($domain){
    $starttime = microtime(true);
    $file      = fsockopen ($domain, 80, $errno, $errstr, 10);
    $stoptime  = microtime(true);
    $status    = 0;

    if (!$file) $status = -1;  // Site is down
    else {
        fclose($file);
        $status = ($stoptime - $starttime) * 1000;
        $status = floor($status);
    }
    return $status;
}
18 голосов
/ 20 мая 2013

В случае, если OP действительно хотел ICMP-Ping, в Примечаниях для пользователей есть несколько предложений для socket_create() [ссылка] , в которых используются необработанные сокеты. Имейте в виду, что в UNIX-подобных системах требуется root-доступ.

Обновление: обратите внимание, что аргумент usec не работает в Windows. Минимальное время ожидания составляет 1 секунду.

В любом случае, это код функции ping с наибольшим количеством голосов:

function ping($host, $timeout = 1) {
    /* ICMP ping packet with a pre-calculated checksum */
    $package = "\x08\x00\x7d\x4b\x00\x00\x00\x00PingHost";
    $socket  = socket_create(AF_INET, SOCK_RAW, 1);
    socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => $timeout, 'usec' => 0));
    socket_connect($socket, $host, null);
    $ts = microtime(true);
    socket_send($socket, $package, strLen($package), 0);
    if (socket_read($socket, 255)) {
        $result = microtime(true) - $ts;
    } else {
        $result = false;
    }
    socket_close($socket);
    return $result;
}
3 голосов
/ 23 марта 2012

Попробуйте это:

echo exec('ping -n 1 -w 1 72.10.169.28');
2 голосов
/ 23 апреля 2016
function ping($ip){
    $output = shell_exec("ping $ip");
    var_dump($output);
}
ping('127.0.0.1');

UPDATE: Если вы передаете жестко закодированный IP-адрес (как в этом примере и в большинстве реальных сценариев), этой функции может быть достаточно.

Но поскольку некоторые пользователи, похоже, очень обеспокоены безопасностью, пожалуйста, напомните, никогда не передает сгенерированные пользователем входные данные в функцию shell_exec: Если IP-адрес исходит из ненадежного источника, по крайней мере, проверьте его с фильтром перед его использованием.

2 голосов
/ 26 июля 2015

Проверка разных портов:

$wait = 1; // wait Timeout In Seconds
$host = 'example.com';
$ports = [
    'http'  => 80,
    'https' => 443,
    'ftp'   => 21,
];

foreach ($ports as $key => $port) {
    $fp = @fsockopen($host, $port, $errCode, $errStr, $wait);
    echo "Ping $host:$port ($key) ==> ";
    if ($fp) {
        echo 'SUCCESS';
        fclose($fp);
    } else {
        echo "ERROR: $errCode - $errStr";
    }
    echo PHP_EOL;
}


// Ping example.com:80 (http) ==> SUCCESS
// Ping example.com:443 (https) ==> SUCCESS
// Ping example.com:21 (ftp) ==> ERROR: 110 - Connection timed out
2 голосов
/ 23 марта 2012

Для этого вам не нужны хаки exec или shell_exec, это возможно сделать на PHP. Книга "Хочешь сделать ЧТО с PHP?" Кевин Шредер, покажи как.

Он использует сокеты и функцию pack(), которая позволяет читать и записывать двоичные протоколы. Что вам нужно сделать, это создать пакет ICMP, что вы можете сделать, используя формат 'CCnnnA *' для создания вашего пакета.

0 голосов
/ 02 апреля 2014

Если вы хотите отправлять ICMP-пакеты в php, вы можете взглянуть на эту реализацию ICMP-пинга в Native-PHP , но я ее не тестировал.

0 голосов
/ 05 августа 2013

socket_create должен запускаться от имени пользователя root в системе UNIX с;

$socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
0 голосов
/ 23 марта 2012

Вы можете использовать exec function

 exec("ping ".$ip);

здесь пример

...