如何使用PHP ping服务器端口?

How can I ping a server port with PHP?

我想要一个PHP脚本,该脚本允许您ping IP地址和端口号(ip:port)。我找到了类似的脚本,但它仅适用于网站,不适用于ip:port

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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地址和端口号,然后得到ping响应。


我认为这个问题的答案可以概括为您的问题。

If what you want to do is find out whether a given host will accept
TCP connections on port 80, you can do this:

1
2
3
4
5
6
7
8
9
$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);

For anything other than TCP it will be more difficult (although since
you specify 80, I guess you are looking for an active HTTP server, so
TCP is what you want). TCP is sequenced and acknowledged, so you will
implicitly receive a returned packet when a connection is successfully
made. Most other transport protocols (commonly UDP, but others as
well) do not behave in this manner, and datagrams will not be
acknowledged unless the overlayed Application Layer protocol
implements it.

The fact that you are asking this question in this manner tells me you
have a fundamental gap in your knowledge on Transport Layer protocols.
You should read up on ICMP and TCP, as well as the OSI Model.

此外,这是对主机执行ping操作的一种更简洁的版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 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() [link]的用户提供的注释中有一些建议,这些建议使用原始套接字。请注意,在类似UNIX的系统上,需要root用户访问权限。

更新:请注意usec参数在Windows上不起作用。最小超时为1秒。

无论如何,这是票数最高的ping函数的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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;
}


试试看:

1
echo exec('ping -n 1 -w 1 72.10.169.28');


1
2
3
4
5
function ping($ip){
    $output = shell_exec("ping $ip");
    var_dump($output);
}
ping('127.0.0.1');

更新:
如果您传递一个硬编码的IP(如本例和大多数实际情况一样),则此功能就足够了。

但是由于某些用户似乎非常关注安全性,请提醒不要将用户生成的输入传递给shell_exec函数:
如果IP来自不受信任的来源,请至少在使用它之前使用过滤器进行检查。


测试不同的端口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$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

socket_create必须以root身份在UNIX系统上运行;

1
$socket = socket_create(AF_UNIX, SOCK_STREAM, 0);

您不需要任何exec或shell_exec骇客即可执行此操作,可以在PHP中进行。这本书"您想用PHP做什么?"凯文·施罗德(Kevin Schroeder)演示如何操作。

它使用套接字和pack()函数,使您可以读写二进制协议。您需要做的是创建一个ICMP数据包,您可以使用" CCnnnA *"格式创建数据包。


您可以使用exec函数

1
 exec("ping".$ip);

此处为示例


如果要在php中发送ICMP数据包,可以查看此Native-PHP ICMP ping实现,但我没有对其进行测试。

编辑:

也许该网站已被黑客入侵,因为似乎文件已被删除,archive.org中有副本,但您无法下载tar球文件,仅联系人电子邮件没有联系表格,但这在以下网址无效archive.org,我们只能等到所有者注意到坐姿下降。