2012-03-23 8 views
34

Desidero uno script PHP che consente di eseguire il ping di un indirizzo IP e di un numero di porta (ip:port). Ho trovato uno script simile ma funziona solo per i siti Web, non ip:port.Come posso eseguire il ping di una porta del server con PHP?

<?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); 

?> 

Voglio questo per un server di gioco.

L'idea è che posso digitare l'indirizzo IP e il numero di porta e ottengo la risposta ping.

+0

Usa [presa collegare] (http://www.php.net/manual/en/function.socket-connect.php) o vedere se il vostro server supporta tcp: // urna – Panagiotis

+2

ping utilizza ICMP: http://php.net/manual/en/function.socket-create.php –

+0

@Panagiotis è quello che sta facendo ... –

risposta

59

Penso che la risposta a this question riassuma il problema con la domanda.

Se ciò che si vuole fare è scoprire se un determinato host accetterà connessioni TCP sulla porta 80, si può fare questo:

$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); 

per qualcosa di diverso TCP che sarà più difficile (anche se dal si specifica 80, suppongo che si stia cercando un server HTTP attivo, quindi TCP è ciò che si desidera). TCP viene sequenziato e riconosciuto, quindi sarà in modo implicito ricevere un pacchetto restituito quando una connessione viene effettuata correttamente con . La maggior parte degli altri protocolli di trasporto (comunemente UDP, ma altri come ) non si comportano in questo modo e i datagrammi non saranno riconosciuti a meno che il protocollo di livello applicazione non lo sovrapponga.

Il fatto che tu stia facendo questa domanda in questo modo mi dice che lo ha una lacuna fondamentale nelle tue conoscenze sui protocolli Transport Layer. Si consiglia di leggere su ICMP e TCP, nonché il OSI Model.

Inoltre, ecco una versione slightly cleaner per eseguire il ping agli host.

// 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

Nota: questa è una citazione dalla domanda collegata, per favore non modificarla pensando che si tratti di un errore di formattazione del codice. Di solito inserisco citazioni pertinenti dai link nei miei post per storicità e in caso di link putrefatto, grazie! :) – ShadowScripter

+0

non funziona con il dominio localhost – JackTurky

+0

Funzionerà con IPv6? – ihue

3

Prova questo:

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

exec è una funzione pericolosa e dovrebbe essere disabilitato di default nel tuo php.ini. – markus

+1

che dire del porto in cui l'ho messo gona – user1288533

+0

@ markus-tharkun concordato. Ma è possibile proteggerlo. Se stai semplicemente usando un input come un IP, trasforma l'IP in int e qualunque cosa e controllalo, ma sì è vero. –

-2

È possibile utilizzare la funzione exec

exec("ping ".$ip); 

here un esempio

+2

exec è una funzione pericolosa e dovrebbe essere disabilitata di default nel tuo php.ini. – markus

+1

hai ragione, ma molti tempi di exec sono il modo semplice per risolvere i problemi: D. Di sicuro devo controllare e disinfettare tutto ciò che inserirò nella funzione exec. – Jackie

+3

exec è pericoloso solo se sei abbastanza matto da lanciare ciecamente l'input dell'utente lì –

2

Non è necessario alcun exec o hack shell_exec per farlo, è possibile farlo in PHP. Il libro "Vuoi fare COSA con PHP?" di Kevin Schroeder, mostra come.

Utilizza le prese e la funzione pack() che consente di leggere e scrivere protocolli binari. Quello che devi fare è creare un pacchetto ICMP, che puoi fare usando il formato 'CCnnnA *' per creare il tuo pacchetto.

+0

C'è un sacco di suggerimenti per creare un ping tramite socket_create sul PHP [socket-create usernotes pagina manuale] (http://php.net /manual/en/function.socket-create.php#usernotes). Tuttavia richiede autorizzazioni root in Linux per eseguirlo. – icc97

+3

UNA GRANDE NOTA. per essere in grado di creare un pacchetto ICMP in linux, devi lavorare con socket e pacchetti RAW, che hanno bisogno di prevs amministrativo. questo significa che devi eseguire Apache come root per poterlo fare! . è più sicuro da solo exec allora! –

13

Nel caso in cui il PO veramente voluto un ICMP-Ping, ci sono alcune proposte all'interno delle Note Contributo dell'Utente socket_create()[link], che utilizzano i socket raw. Essere consapevoli del fatto che su sistemi come UNIX è richiesto l'accesso root.

Aggiornamento: si noti che l'argomento usec non ha alcuna funzione su Windows. Il timeout minimo è 1 secondo.

In ogni caso, questo è il codice della sommità funzione ping deliberato:

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

L'OP dichiara esplicitamente che desidera utilizzare una porta – icc97

+1

ha cambiato il pacchetto $ var in $ package = "\ x08 \ x00 \ x19 \ x2 \ x00 \ x00 \ x00 \ x00 \ x70 \ x69 \ x6 \ x67"; ha ottenuto risultati migliori su Windows quando l'IP è scaduto. Questo era dalla documentazione nel tuo link. Grazie – Hariboo

0

socket_create deve essere eseguito come root su un sistema UNIX con;

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

prova diverse porte:

$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

Sebbene questo codice possa rispondere alla domanda, sarebbe meglio includere un contesto, spiegando come funziona e quando usarlo. Le risposte al solo codice non sono utili a lungo termine. – Bono

+0

passaggio non sicuro IP deselezionato in shell_exec .. – Hariboo

+0

Grazie. La sicurezza Imo dipende dal contesto: ovviamente è consigliabile controllare sempre gli input, ma qui non è l'argomento. Qui voglio fornire il codice più semplice in grado di rispondere alla domanda. Ad ogni modo, qualsiasi suggerimento/modifica è benvenuto! – T30