現在、PHP ベースのプロジェクトで IPv4 および IPv6 アドレスを使用しています。2 つの IP を比較して、どちらが大きいかを判断できるようにする必要があります。たとえば、192.168.1.9 は 192.168.1.1 より大きくなります。これを行うために、inet_ptonとunpackを使用して IP をバイナリ文字列に変換しました(私はip2longに精通していますが、IPv4 に限定されています)。
この方法は最初は問題なく動作するように見えましたが、.32 で終わる IP を下位の IP アドレスと比較すると、間違った結果が得られることがすぐにわかりました。たとえば、192.168.1.0 と 192.168.1.32 を比較すると、スクリプトは 192.168.1.0 が 192.168.1.32 より大きいことを示します。これは、IP の 1 つが .32 で終わる場合にのみ発生します。IP の最初の 3 オクテットは変更でき、結果は同じです。
次の PHP コードは、この問題を説明するページを生成します。
// Loop through every possible last octet, starting with zero
for ($i = 0; $i <= 255; $i++) {
// Define two IPs, with second IP increasing on each loop by 1
$IP1 = "192.168.1.0";
$IP2 = "192.168.1.".$i;
// Convert each IP to a binary string
$IP1_bin = current(unpack("A4",inet_pton($IP1)));
$IP2_bin = current(unpack("A4",inet_pton($IP2)));
// Convert each IP back to human readable format, just to show they were converted properly
$IP1_string = inet_ntop(pack("A4",$IP1_bin));
$IP2_string = inet_ntop(pack("A4",$IP2_bin));
// Compare each IP and echo the result
if ($IP1_bin < $IP2_bin) {echo '<p>'.$IP1_string.' is LESS than '.$IP2_string.'</p>';}
if ($IP1_bin === $IP2_bin) {echo '<p>'.$IP1_string.' is EQUAL to '.$IP2_string.'</p>';}
if ($IP1_bin > $IP2_bin) {echo '<p>'.$IP1_string.' is GREATER than '.$IP2_string.'</p>';}
// I have also tried using strcmp for the binary comparison, with the same result
// if (strcmp($IP1_bin,$IP2_bin) < 0) {echo '<p>'.$IP1_string.' is LESS than '.$IP2_string.'</p>';}
// if (strcmp($IP1_bin,$IP2_bin) === 0) {echo '<p>'.$IP1_string.' iS EQUAL to '.$IP2_string.'</p>';}
// if (strcmp($IP1_bin,$IP2_bin) > 0) {echo '<p>'.$IP1_string.' is GREATER than '.$IP2_string.'</p>';}
}
?>
結果のサンプルを次に示します。
192.168.1.0 is EQUAL to 192.168.1.0
192.168.1.0 is LESS than 192.168.1.1
192.168.1.0 is LESS than 192.168.1.2
192.168.1.0 is LESS than 192.168.1.3
192.168.1.0 is LESS than 192.168.1.4
...
192.168.1.0 is LESS than 192.168.1.31
192.168.1.0 is GREATER than 192.168.1.32
192.168.1.0 is LESS than 192.168.1.33
...
IP を人間が読める形式に戻すと、正しい IP が返されるため、問題は比較にあると思います。バイナリ比較用にstrcmpに切り替えてみましたが、結果は同じでした。
この原因を特定するための助けをいただければ幸いです。サンプル スクリプトに示されている IP 変換および比較方法を使用するつもりはありませんが、IPv4 と IPv6 の両方をサポートする方法に固執する必要があります。ありがとう。
Zend Engine v2.3.0およびionCube PHP Loader v4.6.1を使用して、PHPバージョン5.3.3を実行しています
編集:アンパック形式を「A4」(スペースで埋められた文字列)から「a4」(NULで埋められた文字列)に変更することで問題を解決しました。詳細については、以下の私の回答を参照してください。