2012-03-23 129 views
34

我想要一个PHP脚本,它允许你ping一个IP地址和一个端口号(ip:port)。我发现了一个类似的脚本,但它只适用于网站,而不是ip:port如何用PHP ping服务器端口?

<?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响应。

+0

使用[插座连接(http://www.php.net/manual/en/function.socket-connect.php),或者看看你的服务器支持tcp:// urn – Panagiotis 2012-03-23 15:13:34

+2

ping使用ICMP:http://php.net/manual/en/function.socket-create.php – 2012-03-23 15:14:10

+0

@Panagiotis这就是他在做什么... – 2012-03-23 15:16:50

回答

59

我认为this question的答案几乎总结了您的问题的问题。

如果你想要做的是找出给定主机是否会接受端口80上的 TCP连接的,你可以这样做:

$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协议中的知识存在根本性差距。 您应该阅读ICMPTCP以及OSI Model

此外,这是一个slightly cleaner版本ping主机。

// 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; 
} 
+0

注意:这是来自链接问题的引用,请不要编辑它,因为它是代码格式错误。我通常会将相关链接引用到我的帖子中以获得历史性和链接腐烂的情况,谢谢! :) – ShadowScripter 2013-02-25 18:13:40

+0

它不能与本地主机域 – JackTurky 2013-04-12 16:16:57

+0

这将工作与IPv6? – ihue 2017-04-08 17:43:33

3

试试这个:

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

exec是一个危险的函数,应该是在你的php.ini中默认是禁用的。 – markus 2012-03-23 15:18:07

+1

im gona把它放在哪个港口 – user1288533 2012-03-23 15:19:02

+0

@ markus-tharkun同意。但有可能保护它。如果你只是使用一个输入,如IP,将IP转换为int,然后检查它,但是这是真的。 – 2012-03-23 15:23:32

-2

可以使用exec功能

exec("ping ".$ip); 

here为例

+2

exec是一个危险的功能,应该在你的php.ini中默认禁用。 – markus 2012-03-23 15:17:59

+1

你是对的,但很多时候exec是解决问题的简单方法:D。当然,我必须控制和消毒所有我将要执行的功能。 – Jackie 2012-03-23 16:04:06

+3

exec只有当你足够疯狂,才会盲目地抛出用户输入 – 2014-10-23 01:36:02

2

你不需要任何高管或黑客了shell_exec要做到这一点,有可能在PHP中完成。这本书'你想用PHP做什么?'由凯文施罗德,节目的如何。

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

+0

有一堆建议通过socket_create在PHP上创建ping [socket-create manual page usernotes](http://php.net) /manual/en/function.socket-create.php#usernotes)。但是,它在Linux中需要root权限才能运行它。 – icc97 2013-04-16 14:35:13

+3

ONE BIG NOTE。为了能够在linux中创建ICMP数据包,您必须使用需要管理预配置的RAW套接字和数据包。这意味着你需要以root身份运行apache才能做到这一点! 。然后只要执行就更安全! – 2013-04-23 04:24:15

13

万一OP真正想要的ICMP平,有用户投稿注意事项中的一些建议socket_create()[link],其中使用原始套接字。请注意,在UNIX系统中,系统需要root访问权限。

更新:请注意,usec参数在窗口上没有功能。最短超时时间为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; 
} 
+1

该OP明确说明他想使用端口 – icc97 2013-11-12 12:18:21

+1

将$ package var更改为$ package =“\ x08 \ x00 \ x19 \ x2f \ x00 \ x00 \ x00 \ x00 \ x00 \ x70 \ x69 \ x6e \ x67”;当IP超时时在Windows上获得更好的结果。这是来自您链接中的文档。谢谢 – Hariboo 2016-05-09 16:35:46

0

socket_create需要运行作为UNIX系统上根;

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

测试不同的端口:

$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 
1
function ping($ip){ 
    $output = shell_exec("ping $ip"); 
    var_dump($output); 
} 
ping('127.0.0.1'); 
+0

虽然这段代码可能回答这个问题,但最好包含一些上下文,解释它的工作原理以及何时使用它。从长远来看,仅有代码的答案是没有用的。 – Bono 2016-04-23 14:04:49

+0

不安全通过IP未选中进入shell_exec .. – Hariboo 2016-05-09 16:17:48

+0

谢谢。伊莫安全取决于上下文:当然,建议始终检查输入,但这不是这里的主题。在这里我想提供可以回答问题的最简单的代码。无论如何,任何建议/编辑是值得欢迎的! – T30 2016-05-09 16:30:44