ホームページ  >  記事  >  バックエンド開発  >  PHP マルチスレッド PHP fsockopen ソリューション

PHP マルチスレッド PHP fsockopen ソリューション

不言
不言オリジナル
2018-04-14 16:49:022777ブラウズ

この記事の内容は、php マルチスレッド php fsockopen ソリューションに関するものです。必要な友人は参考にしてください。


質問: php でマルチスレッドを実装する方法はありますか。スレッドについてはどうですか?

複数のサーバーに基づいて PHP アプリケーションを作成しているとします。理想的な状況は、リクエストを次々に送信するのではなく、同時に複数のサーバーに送信することです。

それは可能ですか?

答え:

同時実行機能を実装したいとき、通常は fork や spawn

スレッドの使用を考えますが、PHP がマルチスレッドをサポートしていないことがわかると、気が変わり、十分ではないものを使用する可能性があります。 Perl などの言語。

実際、ほとんどの場合、フォークやスレッドを使用する必要はなく、フォークやスレッドを使用するよりもパフォーマンスが向上します。

n 台の実行中のサーバーがまだ正常に機能していることを確認するサービスを構築するとします。次のようなコードを書くとよいでしょう:


$hosts = array("host1.sample.com", "host2.sample.com", "host3.sample.com");
$timeout = 15; $status = array();
foreach ($hosts as $host) {
$errno = 0;
$errstr = "";
$s = fsockopen($host, 80, $errno, $errstr, $timeout);
if ($s) {
$status[$host] = "Connectedn";
fwrite($s, "HEAD / HTTP/1.0rnHost: $hostrnrn");
do {
$data = fread($s, 8192);
if (strlen($data) == 0) { break; }
$status[$host] .= $data;
} while (true); fclose($s);
} else {
$status[$host] = "Connection failed: $errno $errstrn";
}
}
print_r($status);



正常に動作しますが、fsockopen() がホスト名を分析して接続を確立する前 (または $timeout 秒遅れて)、このコードの展開には時間がかかります多数のサーバーを管理するには時間がかかります。

したがって、このコードを放棄する必要があります。fsockopen が接続ステータスを返すのを待つ必要がなく、非同期接続を確立できます。 PHP は依然としてホスト名を解決する必要があります (そのため、IP を直接使用する方が賢明です) が、接続を開いた後すぐにホスト名が返されるため、次のサーバーに接続できます。
これを実現するには 2 つの方法があります。PHP5 では、新しい stream_socket_client() 関数を使用して fsocketopen() を直接置き換えることができます。 PHP5 より前のバージョンの場合、問題を解決するには自分で実行し、ソケット拡張機能を使用する必要があります。

以下は PHP5 での解決策です:


$hosts = array("host1.sample.com", "host2.sample.com", "host3.sample.com");
$timeout = 15;
$status = array();
$sockets = array();
foreach ($hosts as $id => $host) {
$s = stream_socket_client("$host:80", $errno, $errstr, $timeout,STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT);
if ($s) {
$sockets[$id] = $s;
$status[$id] = "in progress";
} else {
$status[$id] = "failed, $errno $errstr";
}
}
while (count($sockets)) {
$read = $write = $sockets;
$n = stream_select($read, $write, $e = null, $timeout);
if ($n > 0) {
foreach ($read as $r) {
$id = array_search($r, $sockets);
$data = fread($r, 8192);
if (strlen($data) == 0) {
if ($status[$id] == "in progress") {
$status[$id] = "failed to connect";
}
fclose($r);
unset($sockets[$id]);
} else {
$status[$id] .= $data;
}
}
foreach ($write as $w) {
$id = array_search($w, $sockets);
fwrite($w, "HEAD / HTTP/1.0rnHost: " . $hosts[$id] . "rnrn");
$status[$id] = "waiting for response";
}
} else {
foreach ($sockets as $id => $s) {
$status[$id] = "timed out " . $status[$id];
}
break;
}
}
foreach ($hosts as $id => $host) {
echo "Host: $hostn"; echo "Status: " . $status[$id] . "nn";
}



stream_select() を使用してソケットが開く接続イベントを待ちます。 stream_select() は、システムの select(2) 関数を呼び出して機能します。最初の 3 つのパラメータは、使用するストリームの配列であり、(3 つのパラメータごとに) 読み取り、書き込み、例外の取得が可能です。 stream_select() は、$timeout (秒) パラメータを設定することでイベントが発生するのを待つことができます。イベントが発生すると、渡したパラメータに対応するソケット データが書き込まれます。

以下は PHP 4.1.0 以降の実装です。PHP をコンパイルするときにソケット (ext/sockets) サポートを組み込んでいる場合は、上記と同様のコードを使用できますが、使用する必要があるのは streams/ の関数だけです。上記のファイルシステム関数の ext/sockets 関数の実装。主な違いは、接続を確立するために

stream_socket_client() の代わりに次の関数を使用することです:


// This value is correct for Linux, other systems have other values
define('EINPROGRESS', 115);
function non_blocking_connect($host, $port, &$errno, &$errstr, $timeout) {
$ip = gethostbyname($host);
$s = socket_create(AF_INET, SOCK_STREAM, 0);
if (socket_set_nonblock($s)) {
$r = @socket_connect($s, $ip, $port);
if ($r || socket_last_error() == EINPROGRESS) {
$errno = EINPROGRESS; return $s;
}
}
$errno = socket_last_error($s);
$errstr = socket_strerror($errno);
socket_close($s);
return false;
}


ここで、stream_select() をsocket_select()、fread() をsocket_read()、そして
socket_write に置き換えます。 () fwrite() を置き換え、socket_close() を使用して fclose() を置き換えると、スクリプトを実行できます。
PHP5 の進歩は、stream_select() を使用してほぼすべてのストリームを処理できることです。たとえば、これを使用して、インクルード
STDIN を通じてキーボード入力を受け取り、それを配列に保存できます。また、開いたパイプからデータを受け取ることもできます。 proc_open() データを通じて。
PHP4.3.xにストリーム処理機能を持たせたい場合は、fsockopenを非同期で動作させるパッチを用意しました。このパッチは非推奨であり、正式にリリースされた PHP バージョンには表示されません。stream_socket_client() 関数の実装をパッチに含めました。これにより、スクリプトを
PHP5 と互換性を持たせることができます。

関連する推奨事項:

php multi-threading_PHP チュートリアル

以上がPHP マルチスレッド PHP fsockopen ソリューションの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
前の記事:PHPのclearstatcache次の記事:PHPのclearstatcache