高性能PHPネットワークサービスを構築する場合、従来のブロッキングソケット通信モードは、多くの場合、高電流シナリオのニーズを満たすことができません。 PHPネットワークアプリケーションの応答速度とスループット機能を改善するために、 socket_set_nonblock()を使用してsocket_accept()を使用して非ブロッキング通信を実現することは、実行可能で効果的な手段です。この記事では、このテクノロジーの実装を詳細に説明し、参照用の実行可能な例コードを提供します。
デフォルトでは、PHPソケット通信がブロックされます。つまり、プログラムがSocket_Accept()またはSocket_Read()操作を実行すると、クライアント接続またはデータが読み取らない場合、プログラムは待機します。この方法は簡単ですが、プログラムの並行能力を大幅に制限します。
非ブロック通信を使用すると、常に待機するのではなく、クライアント接続やデータなしでプログラムの他の部分を実行し続けることができます。このメカニズムは、多数の短い接続または複数のクライアント要求が同時に受信されるシナリオを処理するのに非常に適しています。
socket_accept() :クライアント接続を受け入れるために使用されます。接続がない場合、接続が発生するまでブロックします。
socket_set_nonblock() : socket_accept()が接続がないためメインスレッドをブロックしないように、ソケットを非ブロッキングモードに設定します。
非ブロッキングモードでは、接続のないため、プロセス全体をブロックすることなく、新しい接続要求ループごとのループをリクエストできます。 Socket_Select()を組み合わせて複数のソケットの状態を投票して、パフォーマンスをさらに最適化できます。
以下は、非ブロッキングソケットを使用した単純なPHPサーバーの例です。
<?php
$host = '0.0.0.0';
$port = 8080;
// 作成するsocket
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($server === false) {
die("socket_create() failed: " . socket_strerror(socket_last_error()));
}
// 設定socket再利用可能
socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
// バインドポート
if (!socket_bind($server, $host, $port)) {
die("socket_bind() failed: " . socket_strerror(socket_last_error($server)));
}
// モニター
if (!socket_listen($server, 5)) {
die("socket_listen() failed: " . socket_strerror(socket_last_error($server)));
}
// 設定为ノンブロッキング
socket_set_nonblock($server);
$clients = [];
echo "サーバーが開始されます,モニター端口 $port ...\n";
while (true) {
// 新しい接続を受け入れます(ノンブロッキング)
$client = @socket_accept($server);
if ($client !== false) {
socket_set_nonblock($client);
$clients[] = $client;
echo "新しいクライアント接続: " . count($clients) . " 接続の総数\n";
}
// クライアントデータを処理します
foreach ($clients as $key => $client) {
$data = @socket_read($client, 1024, PHP_NORMAL_READ);
if ($data === false) {
continue;
}
if ($data === "") {
// クライアントの切断
socket_close($client);
unset($clients[$key]);
echo "クライアントの切断\n";
continue;
}
$data = trim($data);
if ($data) {
echo "受信したデータ: $data\n";
$response = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nHello from m66.net\r\n";
socket_write($client, $response);
socket_close($client);
unset($clients[$key]);
}
}
// 避けるCPU占有100%
usleep(100000);
}
socket_close($server);
?>
socket_set_nonblock()を使用する主な利点は次のとおりです。
メインスレッドをブロックせず、複数の接続を同時に処理できるようにします。
Socket_Select()などの関数と組み合わせると、より複雑なイベントループを実装できます。
チャットルーム、インスタントメッセージング、Websocketサーバーなど、高い並行性シナリオのパフォーマンスを向上させることができます。
非ブロッキングモードでは、 @を使用してエラーを抑制したり、 socket_last_error()を判断するなど、例外処理に注意を払う必要があります。
コードロジックでは、リソースの漏れを回避するために、接続のライフサイクルを積極的に管理する必要があります。
複雑な並行性制御の場合、複数のプロセス( PCNTL_FORK()など)またはCoroutine Frameworks(Swooleなど)を使用することを検討できます。
socket_accept()とsocket_set_nonblock()を組み合わせることにより、phpネットワークアプリケーションの並行性パフォーマンスと応答速度を効果的に改善できます。 PHPは、ネットワークプログラミングの基礎となる言語ほど強力ではありませんが、安定した信頼性の高いネットワークサービスシステムを合理的な方法で構築することができます。この記事が、非ブロッキング通信メカニズムとその実践を理解するのに役立つことを願っています。