Java ではマルチスレッド化は非常に良いことですが、PHP のマルチスレッド化は PHP では使用できないと多くの人が言いますが、実際には、PHP のマルチスレッド化の実装方法は fsockopen 関数に関連しています。さらに詳しく知りたい学生は参考にしてください。
同時実行機能を実装したいとき、通常、フォークまたは生成スレッドを使用することを考えますが、PHP がマルチスレッドをサポートしていないことがわかると、考えを変え、perl などの十分ではない言語を使用する可能性があります。
実際、ほとんどの場合、フォークやスレッドを使用する必要はなく、フォークやスレッドを使用するよりもパフォーマンスが向上します。
実行中のサーバーがまだ正常に機能していることを確認するサービスを構築するとします。次のようなコードを作成できます:
コードは次のとおりです | コードをコピー |
$hosts = array("host1.sample.com", "host2.sample.com") , "host3.sample.com"); $timeout = 15; $status = array(); foreach ($hosts を $host) { $errno = 0; $errstr = ""; $s = 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); fclose($s); } else { $status[$host] = "接続に失敗しました: $errno $errstrn"; } } print_r($status); ? > |
正常に動作しますが、このコードを拡張して多数のサーバーを管理するには、 fsockopen() がホスト名を解析して正常な接続を確立するまで (または $timeout 秒遅れて) 長い時間がかかります。
したがって、このコードを放棄する必要があります。fsockopen が接続ステータスを返すのを待つ必要がなく、非同期接続を確立できます。 PHP は依然としてホスト名を解決する必要があります (したがって、IP を直接使用する方が賢明です) が、接続を開いた後すぐにホスト名が返されるため、次のサーバーに接続できます。
これを実現するには 2 つの方法があります。PHP5 では、新しい stream_socket_client() 関数を使用して fsocketopen() を直接置き換えることができます。 PHP5 より前のバージョンの場合、問題を解決するには自分で実行し、ソケット拡張機能を使用する必要があります。
PHP5 での回避策は次のとおりです:
正常に動作しますが、このコードを拡張して多数のサーバーを管理するには、 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 ($ $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] = "進行中"; } else { $status[$id] = "失敗しました、$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) { 「 progress") { $status[$id] = "接続に失敗しました"; } fclose($r); unset($sockets[$id]); $status[ $id] .= $data; } } /* 書き込み可能なソケットは HTTP リクエストを受け入れることができます */ foreach ($write as $w) { $id = array_search($w, $sockets); fwrite( $w, "HEAD / HTTP/ 1.0rnHost: " . $hosts[$id] . "rnrn"); $status[$id] = "応答待ち"; } } else { /* 待機中にタイムアウトしました; すべてのホストが関連付けられていると想定します * $sockets には問題があります */ foreach ($sockets as $id => $s) { $status[$id] = "タイムアウト " . $status[$id ]; } Break; } } foreach ($hosts as $id => $host) { echo "ホスト: $hostn"; echo "ステータス: " . $status[$id] ; } ?> ; |
コードは次のとおりです | コードをコピー |
// この値は 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, $port); if ($r ||ソケット_last_error() == EINPROGRESS) { $errno = EINPROGRESS; return $s; } } $errno =ソケット_last_error($s); $errstr =ソケット_strerror($errno); ソケット_クローズ($s); return false; } ?> |
ここで、stream_select() をsocket_select()、fread() をsocket_read()、fwrite() をsocket_write()、fclose() をsocket_close()に置き換えて、スクリプトを実行します。
PHP5 の進歩は、stream_select() を使用してほぼすべてのストリームを処理できることです。たとえば、これを使用して、STDIN をインクルードしてキーボード入力を受信し、配列に保存できます。また、開いたパイプからデータを受信することもできます。 proc_open() を通じて。
PHP マルチスレッド クラスを共有しましょう
代码如下 | 复制代 |
* @title: PHP多線程类(Thread) |