ホームページ >バックエンド開発 >PHPチュートリアル >php fsockopenのマルチスレッド問題の解決策 [翻訳]_PHPチュートリアル

php fsockopenのマルチスレッド問題の解決策 [翻訳]_PHPチュートリアル

WBOY
WBOYオリジナル
2016-07-21 15:22:55966ブラウズ

質問:
PHPでマルチスレッドを実装する方法はありますか?
複数のサーバーに基づいて PHP アプリケーションを作成しているとします。理想的な状況は、リクエストを次々に送信するのではなく、同時に複数のサーバーに送信することです。
可能でしょうか?
答え:
同時実行機能を実装したいとき、通常、フォークまたは生成スレッドの使用を考えますが、PHP がマルチスレッドをサポートしていないことがわかると、気が変わり、次のような十分ではない言語を使用する可能性があります。パールとして。
実際、ほとんどの場合、フォークやスレッドを使用する必要はなく、フォークやスレッドを使用するよりもパフォーマンスが向上します。
実行中のサーバーがまだ正常に機能していることを確認するサービスを構築するとします。次のようなコードを記述できます:

コードをコピー コードは次のとおりです:

$hosts = array("host1.sample.com", "host2.sample.com" , " host3.sample.com");
$timeout = 15; $status = array();
$errno = ""; fsockopen( $host, 80, $errno, $errstr, $timeout);
if ($s) {
$status[$host] = "接続済み"
fwrite($s, "HEAD / HTTP/1.0rnHost: $hostrnrn ");
do {
$data = fread($s, 8192);
if (strlen($data) == 0) { Break; }
$status[$host] .= $data;
} while ( true);
} else {
$status[$host] = "接続に失敗しました: $errno $erstrn";
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; ] = "進行中";
} else {
$status[$id] = "失敗しました、$errno $errstr"
}
}
while (count($sockets)) {
$read = $write = $ソケット;
$ 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] == "進行中") {
$ status[$id ] = "接続に失敗しました";
fclose($r);
} else {
$status[$id] .= $data;
}
foreach ($write as $w) {
$id = array_search($w, $sockets);
fwrite($w, "HEAD / HTTP/1.0rnHost: " . $hosts[$id] . "rnrn ");
$status[$id] = "応答待ち";
}
} else {
foreach ($sockets as $id => $s) {
$status[$id] = "タイムアウト " . $status[ $id];
}
}
}
foreach ($hosts as $id => $host) {
echo "ステータス: " . $id] . "nn";
}
?>


ソケットが開く接続イベントを待機します。 stream_select() は、システムの select(2) 関数を呼び出して機能します。最初の 3 つのパラメータは、使用するストリームの配列であり、(3 つのパラメータごとに) 読み取り、書き込み、例外の取得が可能です。 stream_select() は、$timeout (秒) パラメータを設定することでイベントが発生するのを待つことができます。イベントが発生すると、渡したパラメータに対応するソケット データが書き込まれます。
以下は PHP 4.1.0 以降の実装です。PHP のコンパイル時にソケット (ext/sockets) サポートを組み込んでいる場合は、上記と同様のコードを使用できますが、ストリーム/ファイルシステムの関数には ext を使用する必要があります。上記の /sockets 関数の実装。主な違いは、接続を確立するために stream_socket_client() の代わりに次の関数を使用することです:



コードをコピーします

コードは次のとおりです:

// この値は Linux では正しいですが、他のシステムには他の値があります
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) , $ ポート);
if ($r || ソケット_last_error() == EINPROGRESS;
$errno = EINPROGRESS;
$errno = ソケット_last_error($s); $errno );
socket_close($s);
return false;
?>


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



http://www.bkjia.com/PHPjc/324595.html

www.bkjia.com

http://www.bkjia.com/PHPjc/324595.html技術記事質問: PHP でマルチスレッドを実装する方法はありますか? 複数のサーバーに基づいて PHP アプリケーションを作成しているとします。理想的な状況は、... ではなく、複数のサーバーに同時にリクエストを送信することです。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
前の記事:PHP 配列関数シーケンス array_splice() - array_PHP チュートリアルの任意の位置に要素を挿入します次の記事:PHP 配列関数シーケンス array_splice() - array_PHP チュートリアルの任意の位置に要素を挿入します

関連記事

続きを見る