PHPでソケット通信を実施するとき、特に特定のバイナリ形式でデータを転送する必要がある場合は、パッケージ化(カプセル化)してデータを開梱する必要がある状況に遭遇することがよくあります。 Pack()関数は、この問題を解決するための武器です。この記事では、ソケット通信におけるPACK()関数の特定の使用法を説明する簡単な例を組み合わせています。
pack()は、PHPの組み込み関数であり、指定された形式に従ってデータをバイナリ文字列にパッケージ化できます。これにより、処理されたデータはよりコンパクトで、ネットワーク上で送信するのに便利です。
基本的な構文は次のとおりです。
string pack ( string $format , mixed $args [, mixed $... ] )
$フォーマットは、整数、文字、浮動ポイントなどのパッケージングルールを定義するフォーマット文字列です。
後続のパラメーターは、対応する形式のデータです。
ソケット通信中、データはバイトストリームで送信されます。さまざまなマシンのエンディアン性は異なる場合があり、テキストまたは通常のデータを直接送信すると、受信者がエラーを解析する可能性があります。
pack()を使用できます:
固定形式でデータをエンコードして、送信および受信先の形式が一貫していることを確認します。
エンディアンネスの問題を処理します(ビッグエンディアン、リトルエンディアン)。
送信と解析を簡単にするために、固定長のバイナリデータを生成します。
TCPソケットを介してデータパケットを送信すると、フォーマットは次のとおりです。
フィールド | タイプ | 説明します |
---|---|---|
パッケージの長さ | 符号なしショート(2バイト) | パッケージの長さフィールド自体を除くパッケージの長さ |
コマンド番号 | 符号なしショート(2バイト) | コマンドID |
データ | 弦 | 特定のコンテンツ |
<?php
// 送信されたデータをシミュレートします
$command = 1001;
$data = "Hello, socket communication!";
// データの長さを計算します
$dataLen = strlen($data);
// パッケージの長さはコマンド番号の長さです + データの長さ (2 + $dataLen)
$packetLen = 2 + $dataLen;
// 使用 pack パッケージの長さとコマンド番号(ネットワークバイト順序を使用します,ビッグエンディアン)
$header = pack('n', $packetLen) . pack('n', $command);
// 完全なパッケージのスプライシング
$packet = $header . $data;
// 確立されていると仮定します socket 接続する,socket_write データを送信します
// socket_write($socket, $packet, strlen($packet));
echo "发送的二进制データの長さ: " . strlen($packet) . "\n";
echo "バイナリデータ16カテゴリ表現: " . bin2hex($packet) . "\n";
?>
pack( 'n'、$ packetlen)とは、署名のない短い整数(2バイト)とネットワークエンディアン(ビッグエンディアン)に$ packetlenを梱包することを意味します。
パック( 'n'、$ command)同様に、コマンド番号をパックします。
スプライシング後、パッケージはデータコンテンツに従います。
データを受信した後、次のように解析できます。
<?php
// 仮定 $recvData はいから socket バイナリデータをお読みください
// 例えば: $recvData = socket_read($socket, 1024);
// 最初にパッケージの長さとコマンド番号を解析します
$header = substr($recvData, 0, 4);
list($packetLen, $command) = array_values(unpack('npacketLen/command', $header));
// データコンテンツを抽出します
$data = substr($recvData, 4, $packetLen - 2);
echo "パッケージの長さ: $packetLen\n";
echo "コマンド番号: $command\n";
echo "データコンテンツ: $data\n";
?>
Pack()関数は、バイナリデータパッケージの強力なツールであり、さまざまなネットワークプロトコルとバイナリファイル操作に適しています。
ソケット通信では、 Pack()の合理的な使用は、一貫したデータ形式と安定した通信を確保できます。
Unpack()関数と組み合わせると、バイナリデータの解析を簡単に実行できます。
エンディアンネスの問題に特に注意してください。ネットワーク通信は一般に、ネットワークのエンディアンネス(ビッグエンディアンネス)を採用しており、 「n」形式を使用して短い整数をパッケージ化することが最も一般的です。
バイナリプロトコルに基づいてネットワーク通信を行っている場合は、 pack()とunpack()をさらに練習することを強くお勧めします。これにより、パケットを処理する能力が大幅に向上します。