PHPネットワークプログラミングでは、 Socket_Select関数は、多重化(I/Oマルチプレックス)を実装するためのコアツールです。これにより、プログラムは複数のソケットを同時に聴き、どのソケットが読みやすく、書き込み可能か、例外があるかを判断し、ブロッキングと待機を避けて、同時接続を効率的に処理できます。この記事では、実用的なケースを組み合わせて、 Socket_Selectの使用とPHPネットワークプログラミングでのアプリケーションの使用を説明します。
Socket_Selectは、ソケットリソースのセットを監視し、どのソケットが読み取りおよび書き込み操作の準備ができているかを決定するために使用されます。プロトタイプは次のとおりです。
int socket_select(array &$read, array &$write, array &$except, ?int $tv_sec, ?int $tv_usec = null)
$ read :読みやすいかどうかを聞いてください。
$ write :それが書くかどうかを聞いてください
$を除く:例外を聴くソケットアレイ
$ TV_SECおよび$ TV_USEC :タイムアウト(秒とマイクロ秒)
関数は、少なくとも1つのソケットが準備が整うか、タイムアウトが発生するまでブロックし、準備ができたソケットの数を返します。
実際のサーバー開発では、複数のクライアント接続が同時に到着する状況に直面することがよくあります。ブロックSocket_Acceptを使用すると、複数の接続を同時に処理できないため、パフォーマンスのボトルネックに簡単につながる可能性があります。 socket_selectを介して:
複数のクライアント接続を同時に聞いてください
ソケットがデータを持っているときにデータを読み取って、アイドル状態の場合はCPUをブロックしません
効率的なイベント駆動型モデルを実装します
次の例では、複数のクライアント接続をサポートし、すべての人にメッセージをブロードキャストするシンプルなチャットルームサーバーを実装しています。
<?php
// 作成するTCP Socket
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($server, "0.0.0.0", 12345);
socket_listen($server);
$clients = [];
echo "チャットルームサーバーの起動,ポートを聞いてください12345...\n";
while (true) {
// リスニングアレイを作成します,サーバーを含むsocketそしてすべてのクライアントsocket
$readSockets = $clients;
$readSockets[] = $server;
// 使用socket_select読みやすさを待ちますsocket
$write = $except = null;
$numChangedSockets = socket_select($readSockets, $write, $except, 0, 200000);
if ($numChangedSockets === false) {
echo "socket_select エラーが発生しました\n";
break;
} elseif ($numChangedSockets > 0) {
// 新しい接続を聞いてください
if (in_array($server, $readSockets)) {
$newClient = socket_accept($server);
if ($newClient !== false) {
$clients[] = $newClient;
$welcomeMsg = "チャットルームへようこそ!\n";
socket_write($newClient, $welcomeMsg, strlen($welcomeMsg));
echo "新しいクライアントに参加してください,現在の接続番号:" . count($clients) . "\n";
}
// からreadSocketsで取り外されましたserver socket,繰り返し処理を防ぎます
$key = array_search($server, $readSockets);
unset($readSockets[$key]);
}
// クライアントが送信したメッセージを処理します
foreach ($readSockets as $sock) {
$data = @socket_read($sock, 2048, PHP_NORMAL_READ);
if ($data === false || $data === '') {
// クライアントは接続を閉じます
$key = array_search($sock, $clients);
socket_close($sock);
unset($clients[$key]);
echo "クライアントの切断,現在の接続番号:" . count($clients) . "\n";
continue;
}
$data = trim($data);
if ($data) {
echo "メッセージを受け取りました: $data\n";
// すべてのクライアントにメッセージをブロードキャストします
foreach ($clients as $client) {
if ($client != $sock) {
socket_write($client, "ユーザーが言った: $data\n");
}
}
}
}
}
}
socket_close($server);
サーバーは最初にTCPソケットを作成し、ポートにバインドし、接続用にリッスンします。
メインループでは、 $ ReadSocketsにはすべてのクライアントソケットとサーバーリスニングソケットが含まれています。
Socket_Selectを呼び出して、ソケットが読みやすくなるのを待ちます。
サーバーソケットが読み取り可能な場合、クライアントリストに受け入れられて追加された新しい接続があります。
クライアントソケットが読み取り可能な場合、データを読み取り、空の場合は接続を閉じ、それ以外の場合はメッセージをブロードキャストします。
CPUアイドリングを避けるために、0.2秒の非ブロッキングショートタイムアウトを使用します。
Socket_Selectは、マルチ接続I/Oマルチプレックスの鍵であり、ブロックを回避し、サーバーのパフォーマンスを向上させます。
Socket_Selectを使用して、マルチクライアントの同時処理を簡単に実装できます。
チャットルーム、オンラインゲーム、インスタントメッセージング、その他のネットワークアプリケーションシナリオに適しています。
PHPネットワークプログラミングに関するより詳細なチュートリアルとケースを知りたい場合は、 http://gitbox.net/php-network-tutorialにアクセスできます。