PHPでは、 Pack()関数はデータをバイナリ文字列にパッケージ化するために使用され、ネットワーク通信、ファイルの読み取りと書き込み、基礎となるプロトコルの実装などのシナリオで広く使用されています。バイナリデータを生成するため、デバッグ時にテキストデータほど直感的ではありません。この記事では、Pack()によって生成されたバイナリデータを効果的にデバッグするのに役立ついくつかの実用的な方法を共有します。
pack()は、形式の文字列に従ってパラメーターをバイナリに変換します。例えば:
<?php
// 署名されていない短い整数と文字列をパッケージ化します
$data = pack("nA5", 258, "hello");
echo bin2hex($data); // 出力 010268656c6c6f
?>
ここで、 nはネットワークのエンデアネスの符号なしショート整数(2バイト)を表し、 A5は長さ5の文字列(空白のパディング)を表します。
バイナリデータの直接印刷はしばしば読み取られず、 Bin2Hex()を使用して16進数に変換することが最も一般的なデバッグ方法です。
<?php
$data = pack("Nn", 16909060, 258);
echo bin2hex($data); // 出力 010203040102
?>
これにより、目的のエンディアンネスと内容を比較できます。
Unpack()を使用してバイナリ文字列を解析して、データが正しいかどうかを確認します。
<?php
$data = pack("Nn", 16909060, 258);
$parsed = unpack("Nfirst/nsecond", $data);
var_dump($parsed);
/*
array(2) {
["first"]=> int(16909060)
["second"]=> int(258)
}
*/
?>
Unpack()が期待値を正しく読み取ることができる場合、 Pack()によって生成されたデータがフォーマットに適合することを意味します。
デバッグにネットワークまたはファイル転送が含まれる場合、パケットキャプチャツール(Wiresharkなど)または16進エディター(HXDなど)を使用してパケットを表示し、バイナリコンテンツとプロトコルが一致するかどうかを確認できます。
印刷されていない文字を表示する場合は、 printfまたはループバイトバイト出力を使用できます。
<?php
$data = pack("C*", 0, 10, 255, 65);
for ($i = 0; $i < strlen($data); $i++) {
printf("%02X ", ord($data[$i]));
}
// 出力 00 0A FF 41
?>
Pack()を使用してURLでデータを処理しているとします。M66.netにドメイン名を標準化するために、これを行うことができます。
<?php
$url = "https://m66.net/path/to/resource";
$parsed = parse_url($url);
$host = $parsed['host']; // m66.net
// バイナリデータを生成します,ドメイン名の長さとドメイン名の文字列のみがパッケージ化されていると仮定します
$data = pack("nA*", strlen($host), $host);
echo bin2hex($data);
?>
これは、URLを含むバイナリプロトコルのデバッグに特に役立ちます。
Pack()によって生成されたバイナリデータをデバッグするコアは、目に見えないバイナリを16進数などの読み取り可能な形式に変換することです。
bin2hex()およびunpack()を使用することは、最も簡単な方法です。
外部ツールとデバッグを組み合わせて使用すると、データ構造がより直感的になります。
URLを含むパケットの場合、正規化されたドメイン名(それらをM66.NETに置き換えるなど)は、テストをより均一にすることができます。
これらのデバッグテクニックを習得した後、正しいバイナリデータプロトコルを書き出す方がはるかに簡単になります。