6

Sander Steffannは私の以前の質問で言及しました:

0000:0000:0000:0000:0000:0000:192.168.0.1 のようなアドレスは、0000:0000:0000:0000:0000:0000:c0a8:0001 と記述されます。これはまったく同じアドレスですが、16 進数表記です。

アドレスが次のように書かれているかどうかを PHP で検出するにはどうすればよいです::0000:192.168.0.1か? IP ベースの文字列に「.」が含まれているかどうかを確認するだけで十分ですか? と ':' ?0000::0000:192.168.0.10000:0000:0000:0000:0000:0000:192.168.0.1

そして、これを完全な文字列に変更するにはどうすればよい0000:0000:0000:0000:0000:0000:c0a8:0001ですか?

これを IPv4 に変更すると、次のようになります。

<?php 
$strIP = '0000:0000:0000:0000:0000:0000:192.168.0.1';

$strResult = substr($strIP, strrpos($strIP, ':'));

echo $strResult; //192.168.0.1 ?
?>

...または正しい IP 文字列表現は、このスニペットでできることよりも複雑ですか?

4

3 に答える 3

3

最善の策は、これを手動で行うのではなく、呼び出しinet_ptonてバイナリ表現を取得し、それを目的の形式に変換することです。

$foo = inet_pton("::1");
for ($i = 0 ; $i < 8 ; $i++)
    $arr[$i] = sprintf("%02x%02x", ord($foo[$i * 2]), ord($foo[$i * 2 + 1]));
$addr = implode(":", $arr);
于 2013-01-21T19:37:05.963 に答える
3

これを一気に書き上げて、初めてうまくいったなんて信じられません。

$strIP = '0000:0000:0000:0000:0000:0000:192.168.0.1';
$arrIP = explode(':', $strIP);

if( preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $arrIP[count($arrIP)-1]) ) {
  $ip4parts = explode('.', $arrIP[count($arrIP)-1]);
  $ip6trans = sprintf("%02x%02x:%02x%02x", $ip4parts[0], $ip4parts[1], $ip4parts[2], $ip4parts[3]);
  $arrIP[count($arrIP)-1] = $ip6trans;

  $strIP = implode(':', $arrIP);
}
echo $strIP; //output: 0000:0000:0000:0000:0000:0000:c0a8:0001

基本的:

  1. 文字列を爆発させる:
  2. 最後のクワッドが IP4 アドレスのようにフォーマットされているかどうかを確認します
  3. 最後のクワッドを爆発させる.
  4. IP4 オクテットを 2 つの 16 進クワッドに再印刷します
  5. IP4 クワッドを新しいものに交換する
  6. で配列を内破し:ます。
于 2013-01-21T19:23:10.267 に答える
2

まず第一に、住所がどのように書かれているか気にする必要はありません。inet_pton() はすべてのバリエーションを解析し、一貫した結果を提供します。これをバイナリ、16 進数、または必要なものに変換できます。

::192.168.0.1のようなものを変換するためのすべてのコードは、0000:0000:0000:0000:0000:0000:c0a8:0001実際には私の投稿にありました。それがまさに私のサンプル関数が行うことです。

inet_pton()にフィード0000:0000:0000:0000:0000:0000:192.168.0.1し、次に inet_ntop() にフィードすると、正規の IPv6 表記が得られます::192.168.0.1。この場合です。その文字列が で始まり::、残りに:3 つのドットが含まれている場合、それが IPv4 アドレスであると確信できます ;-)

前の質問への回答とこの質問を組み合わせるには:

function expand_ip_address($addr_str) {
  /* First convert to binary, which also does syntax checking */
  $addr_bin = @inet_pton($addr_str);
  if ($addr_bin === FALSE) {
    return FALSE;
  }

  $addr_hex = bin2hex($addr_bin);

  /* See if this is an IPv4-Compatible IPv6 address (deprecated) or an
     IPv4-Mapped IPv6 Address (used when IPv4 connections are mapped to
     an IPv6 sockets and convert it to a normal IPv4 address */
  if (strlen($addr_bin) == 16
  &&  substr($addr_hex, 0, 20) == str_repeat('0', 20)) {
    /* First 80 bits are zero: now see if bits 81-96 are either all 0 or all 1 */
    if (substr($addr_hex, 20, 4) == '0000')
    ||  substr($addr_hex, 20, 4) == 'ffff')) {
      /* Remove leading bits so only the IPv4 bits remain */
      $addr_bin = substr($addr_hex, 12);
    }
  }

  /* Then differentiate between IPv4 and IPv6 */
  if (strlen($addr_bin) == 4) {
    /* IPv4: print each byte as 3 digits and add dots between them */
    $ipv4_bytes = str_split($addr_bin);
    $ipv4_ints = array_map('ord', $ipv4_bytes);
    return vsprintf('%03d.%03d.%03d.%03d', $ipv4_ints);
  } else {
    /* IPv6: print as hex and add colons between each group of 4 hex digits */
    return implode(':', str_split($addr_hex, 4));
  }
}
于 2013-01-21T21:27:08.727 に答える