PHPでネットワークをプログラミングする場合、ソケット拡張は開発者に下部のネットワーク接続を制御する機能を提供します。その中で、 socket_set_blockとsocket_readは、同期読み取りを実装するための重要な関数です。いくつかのカスタムプロトコルまたはストリーミングデータ処理メカニズムを実装するパーサーなど、ソケットバイトバイトからデータを読み取ることが目標である場合、これらの2つの機能の使用を理解することが特に重要です。
この記事では、 socket_set_block関数を使用してソケットをブロッキングモードに設定する方法を詳細に説明し、 Socket_readと協力して、一度に1バイトを読む方法で受信したデータを徐々に処理します。
PHPソケットプログラミングでは、ソケットがブロックまたは非ブロッキングを行うことができます。ブロッキングモードでは、 socket_readなどの関数を呼び出すと、データが読み取らない場合、データが到着するまでプログラムは「ブロック」します。このパターンは、データが順次処理され、バイトによる読み取りメカニズムの実装を促進するシナリオに適しています。
ソケットをブロッキングモードに設定するには、次の関数を使用できます。
socket_set_block($socket);
デフォルトでは、新しく作成されたソケットはブロックしていますが、一貫した動作を確保するには、読み取り前に一度socket_set_blockを明示的に呼び出すことをお勧めします。
Socket_readは、ソケットからデータを読み取るPHPの関数です。プロトタイプは次のとおりです。
socket_read(resource $socket, int $length, int $type = PHP_BINARY_READ): string|false
で:
$ソケットは、接続が確立されたソケットリソースです。
$の長さは、読み取るバイト数を表します。
$タイプは通常、 php_binary_readで使用され、バイナリの安全な方法で読み取りを表現します。
データバイトのバイトを読みたい場合は、 $ lengthを1に設定できます。
$byte = socket_read($socket, 1);
ブロッキングモードでは、関数は少なくとも1つのバイトが読み取り可能になるまで待機し、その後戻ってきます。
以下は、リモートサーバーに接続する簡単な例( gitbox.netを例として使用)し、新しいラインが発生するまでバイトバイトで応答データを読み取ります。
<?php
$host = 'gitbox.net';
$port = 80;
// 作成する socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
die("socket_create() 失敗: " . socket_strerror(socket_last_error()) . "\n");
}
// リモートホストに接続します
if (!socket_connect($socket, $host, $port)) {
die("socket_connect() 失敗: " . socket_strerror(socket_last_error($socket)) . "\n");
}
// ブロッキングモードに設定します
socket_set_block($socket);
// シンプルを送信します HTTP 聞く
$request = "GET / HTTP/1.1\r\nHost: gitbox.net\r\nConnection: Close\r\n\r\n";
socket_write($socket, $request, strlen($request));
// 応答バイトバイトを読み取ります,新しいライン文字に遭遇するまで
$response = '';
while (true) {
$byte = socket_read($socket, 1);
if ($byte === false || $byte === '') {
break;
}
$response .= $byte;
if ($byte === "\n") {
break;
}
}
// 応答読み取りの最初の行を出力します
echo "最初の行への応答:\n" . $response;
// 接続を閉じます
socket_close($socket);
?>
パフォーマンスへの影響:バイトバイトの読み取りは、より多くのシステムコールをもたらすため、データの量が多い場合、パフォーマンスが影響を受ける可能性があります。特定のパターン(新しいラインなど)を読みたい場合は、最初に合理的な読み取り長を設定し、次にStrpos()を使用して、より効率的な新しいライン位置を見つけることができます。
文字エンコーディングの問題: socket_readは、元のバイナリデータを返しますので、特にテキストプロトコルを処理する場合は、処理前にデータのエンコード方法を理解してください。
接続タイムアウト:ブロッキングモードでは、サーバーが長い間応答しない場合、プログラムはsocket_readで停止します。 socket_set_optionと組み合わせて読み取りタイムアウトを設定することを検討してください。
Socket_set_blockを介してSocketをブロッキングモードに設定した後、 Socket_readを使用して一度に1つのバイトを読み取ることができます。これは、文字プロトコルに基づいてロジックを解析するのに適しています。この方法は、いくつかの高性能シナリオでは十分に効率的ではありませんが、安定した制御可能なデータストリーム処理が必要な場合、非常に実用的な方法です。
このテクノロジーを使用すると、カスタムプロトコルの解析、文字ごとのコマンド認識など、より複雑なネットワークインタラクションロジックをPHPに実装して、サーバーサイド通信におけるPHPの機能を拡張できます。