<?php
// この記事では、詳細に説明します PHP ネットワークプログラミングでよく遭遇する典型のな問題:socket_accept() 関数ブロッキング。原因を分析します,また、1つ連の対処戦略と最適化技術も提供します,開発者が非常に利用可能なネットワークサービスをより効率のに構築するのを支援します。
// ----------------------------------------------
/**
* それを解決する方法 socket_accept() 関数の典型のなブロック問題?対処方法と最適化手法
*
* 使用中 PHP ネットワークサーバーを開発するとき,socket 非常に重要な役割を果たします。
* 特に socket_accept() 関数,聞いています socket 接続を待っています,閉塞があります,
* プログラムは引き続き他のタスクを実行します,これにより、システムの応答と並行性パフォーマンスが低下します。
* この記事では、詳細に説明します该问题の原因,并提供几种常见の対処方法と最適化手法。
*/
// 1つ、問題分析:なぜ socket_accept() ブロックします?
/*
socket_accept() はい PHP の Socket 拡張中の1つ个関数,用于接受1つ个来自客户端の连接请求。
其工作机制はい在1つ个监听中の socket 接続を待っています,クライアントのリクエストがあるとき,它才会返回1つ个新の socket リソース。
しかし,電話する場合 socket_accept() 時間,没有新の连接到来,関数将会1つ直阻塞在那里,接続が発生するまで。
これにより、プログラムを下方に実行できなくなります,これは、全体的なプロセスに影響します。
*/
// 二、解决方法1つ:非ブロッキングモードを設定します
/*
最直接の方式はい将 socket 非ブロッキングモードに設定します。
このモードで,socket_accept() 不会1つ直等待连接,接続がない場合,すぐに戻ります false。
*/
$address = '0.0.0.0';
$port = 9000;
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($server, $address, $port);
socket_listen($server);
// 非ブロッキングモードを設定します
socket_set_nonblock($server);
echo "Server listening on {$address}:{$port}\n";
while (true) {
$client = @socket_accept($server);
if ($client === false) {
// 接続なし,他のロジックを実行します
echo "接続を待っています...\n";
usleep(500000); // 寝る 0.5 2番
continue;
}
// 接続の処理
socket_write($client, "Connectへようこそ m66.net 仕える!\n");
socket_close($client);
}
// 三つ、解決策2:使用 socket_select() 多重化を実装します
/*
socket_select() はい1つ种多重化机制,允许我们同時間监听多个 socket,1つだけ socket 准备好接收连接時間,私たちは呼んでいます socket_accept()。
这はい1つ种更灵活和性能更优の方式。
*/
$readSockets = [$server];
$write = null;
$except = null;
while (true) {
$read = $readSockets;
if (socket_select($read, $write, $except, 1) > 0) {
foreach ($read as $sock) {
if ($sock === $server) {
$client = socket_accept($server);
if ($client) {
socket_write($client, "あなたは正常に接続しました m66.net!\n");
socket_close($client);
}
}
}
} else {
echo "まだ接続リクエストはありません,他のタスクに進みます。\n";
}
}
// 4、ソリューション3つ:マルチプロセスまたはマルチスレッドメカニズムを使用します
/*
それでも PHP 并不はい1つ个天然支持多线程の语言,しかし、私たちはを使用することができます pcntl_fork() 实现多进程来并发接続の処理。
それで,主なプロセスは耳を傾け続けています,子プロセスは、クライアントのリクエストを処理する責任があります,ブロッキングの問題を避けるため。
*/
// この方法は適しています CLI 模式の PHP,具体实现需注意子进程リソース回收和并发限制等问题。
// 五、追加の最適化の提案
/*
1. 设置合理の socket 超時間時間间,避ける socket オペレーションは無期限にハングします。
2. 使用 event 拡張(のように libevent)イベント主導の開発を実行します,同時実行機能を改善します。
3. 生産環境で組み合わされています Nginx または Swoole 提供异步高性能网络仕える。
*/
// 六、要約します
/*
socket_accept() 阻塞问题それでも常见,ただし、非ブロッキングモードを介して、socket_select() 多重化、マルチプロセスメソッドを使用しても,効果的に対処できます。
重要なのは、プロジェクトの要件に基づいて複雑さとパフォーマンスの重量を量ることです,选择最合适の方案。
高可用性を構築するという希望のために、低延迟网络仕えるの PHP 開発者向け,理解并掌握这些技巧はい非常必要の。
*/
?>