Helping ordinary people create extraordinary websites!
HOME TUTORIALS SCRIPTS WEB HOSTING BLOG FORUM
Get Our Newsletter
Email:

Port Scanning and Service Status Checking in PHP

By Akash Mehta
2008-06-06


Our Implementation

To produce something similar to the server status screenshot we saw earlier, we'll build a simple function to test a given port on the local machine. We'll then incorporate it into a very basic status interface.

In a production scenario, make sure your testing script is on another server. If your web server goes down, your testing script will as well; if your network is experiencing problems, your testing script will not be able to detect these when scanning the local machine. We'll use localhost in this example for simplicity's sake, but seperate hosting for a testing script is crucial in production.

Working with sockets

We can easily give fsockopen a hostname, but we can also give it an IP address. In this case, we probably want to check the local server's status, but checking service status on a remote server is also an option. We'll use 127.0.0.1 to check the local server. We also need to make sure we close each connection if we succesfully establish it.

We can build the socket code in a very simple function similar to the port scanning example:

<?php
function check_port($port) {
$conn = @fsockopen("127.0.0.1", $port, $errno, $errstr, 2);
if ($conn) {
fclose($conn);
return true;
}
}

Here we have added a few parameters to the fsockopen function call. The first two, for the error number and string, point to variables that the function can use to store the respective error information. Most important, however, is the '2' at the end - this is the timeout for the connection in seconds. If the connection isn't established in 2 seconds (which should be more than enough for a local connection), the connection attempt is aborted and considered a failure. Keep in mind that, for each service that is offline, the system will wait a further 2 seconds before generating the report. If your page is taking too long to load, the end user may suspect the entire server is offline!

Checking the services

Now, this will do our standard test on whether or not a connection can be established to the local server on the given port. Next, we need a simple system to check for common ports. We can hardcode this section - we'll always know what we want to check for. Here are some common ports you might want to watch out for:

21 FTP
22 SSH
25 SMTP
80 HTTP
110 POP3
143 IMAP
3306 MySQL

This page has a good list of common ports you may find useful.

We can encode these in a simple associative array within a secondary function that generates the status output as another array.

<?php
function server_report() {
$report = array();
$svcs = array('21'=>'FTP',
'22'=>'SSH',
'25'=>'SMTP',
'80'=>'HTTP',
'110'=>'POP3',
'143'=>'IMAP',
'3306'=>'MySQL');
foreach ($svcs as $port=>$service) {
$report[$service] = check_port($port);
}
return $report;
}

$report = server_report();

Using the data

Once this code executes (given the previous check_port function), our $report variable now holds an associative array indexed by the name of the service, with a value of either true or false (well, 0 or 1). We can then very easily display this in a table:

<table>
<tr>
<td>Service</td>
<td>Status</td>
</tr>
<tr>
<td>FTP</td>
<td><?php echo $report['FTP'] ? "Online" : "Offline"; ?></td>
</tr>
<tr>
<td>SSH</td>
<td><?php echo $report['SSH'] ? "Online" : "Offline"; ?></td>
</tr>
...
</table>

And so on. Now that we have a basic system in place, we can easily introduce visual status indicators (e.g. green / red light icons), or do more with the data (e.g. logging).

We're done!

Here's the completed code:

<?php
function check_port($port) {
$conn = @fsockopen("127.0.0.1", $port, $errno, $errstr, 0.2);
if ($conn) {
fclose($conn);
return true;
}
}

function server_report() {
$report = array();
$svcs = array('21'=>'FTP',
'22'=>'SSH',
'25'=>'SMTP',
'80'=>'HTTP',
'110'=>'POP3',
'143'=>'IMAP',
'3306'=>'MySQL');
foreach ($svcs as $port=>$service) {
$report[$service] = check_port($port);
}
return $report;
}

$report = server_report();
?>
<table>
<tr>
<td>Service</td>
<td>Status</td>
</tr>
<tr>
<td>FTP</td>
<td><?php echo $report['FTP'] ? "Online" : "Offline"; ?></td>
</tr>
<tr>
<td>SSH</td>
<td><?php echo $report['SSH'] ? "Online" : "Offline"; ?></td>
</tr>
<tr>
<td>SMTP</td>
<td><?php echo $report['SMTP'] ? "Online" : "Offline"; ?></td>
</tr>
<tr>
<td>HTTP</td>
<td><?php echo $report['HTTP'] ? "Online" : "Offline"; ?></td>
</tr>
<tr>
<td>POP3</td>
<td><?php echo $report['POP3'] ? "Online" : "Offline"; ?></td>
</tr>
<tr>
<td>IMAP</td>
<td><?php echo $report['IMAP'] ? "Online" : "Offline"; ?></td>
</tr>
<tr>
<td>MySQL</td>
<td><?php echo $report['MySQL'] ? "Online" : "Offline"; ?></td>
</tr>
</table>

In a production application, you can easily abstract the status checking logic from the report HTML and store service info in a database.



Tutorial Pages:
» Introduction
» Service Checking 101
» Our Implementation
» Advanced Status Checking


Related Tutorials:
» Zend Framework Tutorial
» Web Database Access from Desktop Applications
» CubeCart 3.0 Installation and Configuration
» PHP Site Search Made Easy
» Installing and Configuring Drupal 6.1
» Desktop Application Development with PHP-GTK

Ask A Question
characters left.