Как я могу пропинговать порт сервера с помощью PHP?
Мне нужен 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 answers
Я думаю, что ответ на этот вопрос в значительной степени подводит итог проблеме с вашим вопросом.
Если то, что вы хотите сделать, это выяснить, примет ли данный хост 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, но также и другие ) ведут себя не так, и дейтаграммы не будут подтверждены, если только протокол наложенного прикладного уровня реализует это.
Тот факт, что вы задаете этот вопрос таким образом, говорит мне о том, что у вас есть фундаментальный пробел в ваших знаниях о протоколах транспортного уровня. Вы должны прочитать о 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;
}
В случае, если OP действительно хотел ICMP-Ping, в примечаниях, внесенных пользователем, есть несколько предложений socket_create()
[ ссылка], в которых используются необработанные сокеты. Имейте в виду, что в UNIX-подобных системах требуется корневой доступ.
Обновление: обратите внимание, что аргумент 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;
}
Попробуйте это:
echo exec('ping -n 1 -w 1 72.10.169.28');
Для этого вам не нужны никакие хаки exec или shell_exec, это можно сделать на PHP. Книга "Что вы хотите сделать с PHP?" Кевина Шредера, показывает, как это делается.
Он использует сокеты и функцию pack()
, которая позволяет вам читать и записывать двоичные протоколы. Что вам нужно сделать, так это создать пакет ICMP, что вы можете сделать, используя формат "CCNNNA*" для создания своего пакета.
Протестируйте различные порты:
$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
function ping($ip){
$output = shell_exec("ping $ip");
var_dump($output);
}
ping('127.0.0.1');
ОБНОВЛЕНИЕ: Если вы передадите жестко закодированный IP-адрес (как в этом примере и в большинстве реальных сценариев), этой функции может быть достаточно.
Но поскольку некоторые пользователи, похоже, очень обеспокоены безопасностью, пожалуйста, напомните никогда не передавать пользовательские входные данные в функцию shell_exec
:
Если IP-адрес получен из ненадежного источника, по крайней мере, проверьте его с помощью фильтра перед его использованием.
Socket_create должен запускаться от имени root в системе UNIX с;
$socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
Если вы хотите отправлять ICMP-пакеты на php, вы можете взглянуть на эту Нативную реализацию ICMP-пинга на PHP, но я ее не тестировал.