Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Status checker for hundreds IP addresses

Tags:

php

status

I wonder how to make a status checker, checking about 500 addresses in a few minutes? (it'll check a certain port if its listening).

But I care about the performance... so I don't know if it can be done with PHP. Waiting for your suggestions guys.

Also please give me some examples, if you think that the best way for this thing will be PHP or C#.

Ofc. I meant the TCP connection but not http, since I need to check open port for example: 11740

Edit:

Added third bounty for this question! Please post some better answer than those already posted.

like image 922
Cyclone Avatar asked Jan 21 '12 21:01

Cyclone


3 Answers

This is very doable in PHP and you could check 500 IP in a few seconds. Use mutli-curl to send out many requests at once (i.e. 100 or all 500). It will take only as long as the slowest IP to respond. But you may want to set a reasonable curl connect timeout of a few seconds. Default network timeout is 2 minutes as I recall. http://php.net/manual/en/function.curl-multi-exec.php

Note that I'm not saying PHP is your best choice for something like this. But it can be done fairly quickly and easily in PHP.

Here is a full code example. I tested it with real URLs and it all worked. The $results array will contain just about all the stats you can get from a curl request. In your case, since you just care if the port is "open" you do a HEAD request by setting CURLOPT_NOBODY to true.

$urls    = array(
    'http://url1.com'=>'8080',
    'http://url2'=>'80',
    );
$mh        = curl_multi_init();
$url_count    = count($urls);
$i        = 0;
foreach ($urls as $url=>$port) {
    $ch[$i] = curl_init();
    curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch[$i], CURLOPT_NOBODY, true);
    curl_setopt($ch[$i], CURLOPT_URL, $url);
    curl_setopt($ch[$i], CURLOPT_PORT, $port);
    curl_multi_add_handle($mh, $ch[$i]);
    $i++;
}
$running    = null;
do {
    $status    = curl_multi_exec($mh,$running);
    $info     = curl_multi_info_read($mh);
} while ($status == CURLM_CALL_MULTI_PERFORM || $running);

$results= array();
for($i = 0; $i < $url_count; $i++) {
    $results[$i]     = curl_getinfo($ch[$i]);
    // append port number request to URL
    $results[$i]['url']    .= ':'.$urls[$results[$i]['url']];
    if ($results[$i]['http_code']==200) {
        echo $results[$i]['url']. " is ok\n";
    } else {
        echo $results[$i]['url']. " is not ok\n";
    }
    curl_multi_remove_handle($mh, $ch[$i]);
}

curl_multi_close($mh);
print_r($results);
like image 55
Brent Baisley Avatar answered Oct 20 '22 19:10

Brent Baisley


Your best bet might be to use a dedicated port scanner like nmap. I don't know the command-line options off the top of my head, but it should be possible to output a results file and just parse it from PHP.

like image 32
CoderMD666 Avatar answered Oct 20 '22 21:10

CoderMD666


Here is a way to do this very quickly in PHP using the sockets extension, by setting all the sockets to non blocking. From a purely networking point of view, this is the most efficient way, since this simply tests the TCP connectivity and does not exchange any actual data. Tested on PHP/5.2.17-Win32.

<?php

  // An array of hosts to check
  $addresses = array(
    '192.168.40.40',
    '192.168.5.150',
    '192.168.5.152',
    'google.com',
    '192.168.5.155',
    '192.168.5.20'
  );
  // The TCP port to test
  $testport = 80;
  // The length of time in seconds to allow host to respond
  $waitTimeout = 5;

  // Loop addresses and create a socket for each
  $socks = array();
  foreach ($addresses as $address) {
    if (!$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) {
      echo "Could not create socket for $address\n";
      continue;
    } else echo "Created socket for $address\n";
    socket_set_nonblock($sock);
    // Suppress the error here, it will always throw a warning because the
    // socket is in non blocking mode
    @socket_connect($sock, $address, $testport);
    $socks[$address] = $sock;
  }

  // Sleep to allow sockets to respond
  // In theory you could just pass $waitTimeout to socket_select() but this can
  // be buggy with non blocking sockets
  sleep($waitTimeout);

  // Check the sockets that have connected
  $w = $socks;
  $r = $e = NULL;
  $count = socket_select($r, $w, $e, 0);
  echo "$count sockets connected successfully\n";

  // Loop connected sockets and retrieve the addresses that connected
  foreach ($w as $sock) {
    $address = array_search($sock, $socks);
    echo "$address connected successfully\n";
    @socket_close($sock);
  }

/* Output something like:

Created socket for 192.168.40.40
Created socket for 192.168.5.150
Created socket for 192.168.5.152
Created socket for google.com
Created socket for 192.168.5.155
Created socket for 192.168.5.20
4 sockets connected successfully
192.168.40.40 connected successfully
192.168.5.150 connected successfully
google.com connected successfully
192.168.5.20 connected successfully

*/
like image 31
DaveRandom Avatar answered Oct 20 '22 19:10

DaveRandom