Backend Development 6 min read

Implementing Ping Using ICMP Raw Sockets in PHP

This tutorial explains how to use PHP's raw socket functions to construct and send an ICMP echo request packet, calculate its checksum, receive the reply, and wrap the logic into a reusable ping($host, $retry) function for backend network diagnostics.

php中文网 Courses
php中文网 Courses
php中文网 Courses
Implementing Ping Using ICMP Raw Sockets in PHP

To reliably determine whether a remote host is online, the article proposes using ICMP ping instead of checking open ports, which can give false negatives when ports are closed.

An ICMP echo request packet consists of an 8‑bit type, 8‑bit code, 16‑bit checksum, 16‑bit identifier, 16‑bit sequence number, and optional data payload.

First, the packet is built in PHP using raw socket functions:

<code>$package = chr(8).chr(0); // type 8 (echo), code 0
$package .= chr(0).chr(0); // placeholder for checksum
$package .= "R"."C"; // identifier (arbitrary)
$package .= chr(0).chr(1); // sequence number (arbitrary)
for ($i = strlen($package); $i < 64; $i++) {
    $package .= chr(0); // pad to 64 bytes
}</code>

The checksum is then calculated by treating the packet as an array of 16‑bit words, summing them, folding the overflow, and applying bitwise NOT:

<code>$tmp = unpack("n*", $package);
$sum = array_sum($tmp);
$sum = ($sum >> 16) + ($sum & 0xFFFF);
$sum = $sum + ($sum >> 16);
$sum = ~ $sum;
$checksum = pack("n*", $sum);</code>

The computed checksum bytes are inserted back into the packet:

<code>$package[2] = $checksum[0];
$package[3] = $checksum[1]; // fill checksum</code>

With the packet ready, a raw socket is created, the packet is sent, and the script waits for a reply using socket_select . Errors such as timeout or socket failures are handled, and the response is parsed to extract length, TTL, sequence number, and round‑trip time:

<code>$socket = socket_create(AF_INET, SOCK_RAW, getprotobyname('icmp'));
$start = microtime();
socket_sendto($socket, $package, strlen($package), 0, $host, 0);
$read = array($socket);
$select = socket_select($read, $write, $except, 5);
// error handling omitted for brevity
socket_recvfrom($socket, $recv, 65535, 0, $host, $port);
$end = microtime();
$recv = unpack("C*", $recv);
$length = count($recv) - 20; // subtract IP header
$ttl = $recv[9];
$seq = $recv[28];
$duration = round(($end - $start) * 1000, 3);
echo "{$length} bytes from {$host}: icmp_seq={$seq}  ttl={$ttl} time={$duration}ms\n";
socket_close($socket);</code>

Running the script produces output similar to:

<code>64 bytes from 192.168.1.1: icmp_seq=1  ttl=128 time=0.589ms</code>

Finally, all the above logic is encapsulated in a reusable function ping($host, $retry = 1) , which can be called from any PHP code to perform a single ICMP ping and return the formatted result.

pingNetwork ProgrammingICMPraw sockets
php中文网 Courses
Written by

php中文网 Courses

php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.