ネットワークプログラミングでは、特に特定のプロトコルを実装する場合は、RAWバイナリデータをリモートサーバーに送信する必要がある場合があります。 PHPは、指定された形式でデータをバイナリ文字列にパッケージ化できる非常に強力な機能パック()を提供します。 Stream_Socket_Client()と組み合わせて、この生データをTCPまたはUDP接続を介して簡単に送信できます。
この記事では、PHPのPack()関数を使用してデータをパッケージ化し、 Stream_Socket_Client()を介して指定されたサーバーに送信する方法を詳細に紹介します。
Pack()関数は、データをバイナリ文字列に変換するために使用されます。その最初のパラメーターはフォーマット文字列であり、その後のパラメーターはパッケージ化されるデータです。フォーマット文字列には、次のようなさまざまなフォーマットコードが含まれています。
C - 署名されていない文字(1バイト)
n - 署名されていない短い整数(2バイト、大きなエンディアン)
n - 署名の長いロング(4バイト、ビッグエンディアン)
a - nul文字塗りつぶされた文字列
A - スペースが充填された文字列
例えば:
$data = pack('Cnn', 0x01, 300, 400);
ここでは、 0x01はバイトで、 300と400は両方とも2バイトの署名されていない整数です。
Stream_Socket_Client()は、クライアントのネットワーク接続を作成するために使用され、TCP、UDP、およびその他のプロトコルをサポートできます。一般的な構文は次のとおりです。
$socket = stream_socket_client("tcp://m66.net:12345", $errno, $errstr, 30);
最初のパラメーターはアドレス、形式はtcp:// domain name:portです
接続がリソースを正常に返し、障害がfalseを返します
$ errnoおよび$ errstrはエラーコードとエラーメッセージを返します
最後のパラメーターはタイムアウト時間(秒)です
この接続を通じて、 fwrite()を使用してデータとfread()を送信してデータを受信できます。
プロトコルパケットをサーバーに送信する必要があると仮定すると、フォーマットは次のとおりです。
0x10に固定された1バイトコマンドコード
2バイトのユーザーID、Big Endian
4バイトタイムスタンプ、ビッグエンディアン
8バイト文字列(8バイト未満の場合、スペースパディング)
PHPコードの例:
<?php
// ターゲットサーバー情報
$host = "m66.net";
$port = 12345;
// 作成する TCP 接続する
$socket = stream_socket_client("tcp://$host:$port", $errno, $errstr, 10);
if (!$socket) {
die("接続する失败: $errstr ($errno)\n");
}
// データを準備します
$command = 0x10;
$userId = 1025;
$timestamp = time();
$username = "user123";
// パッケージングデータ
// C - 1バイト符号なし整数
// n - 2バイト符号なしショート整数(ビッグエンディアン)
// N - 4バイト符号なしの長い整数(ビッグエンディアン)
// A8 - 長さはです8弦,スペース充填
$packedData = pack('CnNA8', $command, $userId, $timestamp, $username);
// データを送信します
fwrite($socket, $packedData);
// サーバーの応答を読み取ります(サーバーが返されると仮定します 4 バイト応答コード)
$response = fread($socket, 4);
if ($response !== false) {
$responseCode = unpack('N', $response)[1];
echo "サーバー応答コード: $responseCode\n";
} else {
echo "サーバーの応答は受信されていません\n";
}
fclose($socket);
Pack()を使用すると、さまざまなデータ型をネットワーク伝送に適したバイナリデータに簡単に変換できます。
Stream_Socket_Client()は、ネットワーク接続を作成し、複数のプロトコルをサポートするために使用されます。
バイナリデータを送信するときは、両当事者がプロトコル形式、特にデータの長さとバイトの順序を一貫して理解していることを確認してください。
データを読み取るときは、 unpack()を使用して元のバイナリデータを解析する必要があります。