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:

$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
}

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:

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

The computed checksum bytes are inserted back into the packet:

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

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:

$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
";
socket_close($socket);

Running the script produces output similar to:

64 bytes from 192.168.1.1: icmp_seq=1  ttl=128 time=0.589ms

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendpingPHPNetwork 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

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.