Heim >Backend-Entwicklung >PHP-Tutorial >PHP-Multithread-PHP-fsockopen-Lösung
Der Inhalt, der in diesem Artikel mit Ihnen geteilt wird, handelt von der PHP-Multithread-Lösung fsockopen. Freunde in Not können sich darauf beziehen
Frage:
Gibt es eine Möglichkeit, Multithreading in PHP zu implementieren?
Angenommen, Sie schreiben eine PHP-Anwendung, die auf mehreren Servern basiert. Im Idealfall senden Sie Anfragen gleichzeitig an mehrere Server und nicht nacheinander.
Ist es möglich?
Antwort:
Wenn jemand Parallelitätsfunktionen implementieren möchte, denkt er normalerweise an die Verwendung von Fork- oder Spawn-Threads, stellt jedoch fest, dass PHP kein Multithreading unterstützt Möglicherweise ändern Sie Ihre Meinung und verwenden einige Sprachen, die nicht gut genug sind, z. B. Perl.
$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);
Wir müssen diesen Code also aufgeben; wir können eine asynchrone Verbindung herstellen – wir müssen nicht warten, bis fsockopen den Verbindungsstatus zurückgibt. PHP muss den Hostnamen noch auflösen (daher ist es sinnvoller, die IP direkt zu verwenden), aber er kehrt sofort nach dem Öffnen einer Verbindung zurück und wir können uns dann mit dem nächsten Server verbinden.
Es gibt zwei Möglichkeiten, dies zu erreichen; in PHP5 können Sie die neue Funktion stream_socket_client() verwenden, um fsocketopen() direkt zu ersetzen. Bei Versionen vor PHP5 müssen Sie es selbst tun und die Sockets-Erweiterung verwenden, um das Problem zu lösen.
$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_socket_client() die folgende Funktion verwenden, um die Verbindung herzustellen:
// 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; }
jetzt ersetzt durch socket_select() Entfernen Sie stream_select(), ersetzen Sie fread() durch socket_read(), ersetzen Sie fwrite() durch
socket_write(), ersetzen Sie fclose() durch socket_close() und Sie können das Skript ausführen!
Der Fortschritt von PHP5 besteht darin, dass Sie stream_select() verwenden können, um fast alle Streams zu verarbeiten. Sie können damit beispielsweise Tastatureingaben empfangen und über include
STDIN in einem Array speichern und öffnen Sie es über proc_open()-Daten in der Pipeline.
Wenn Sie möchten, dass PHP4.3.x die Funktion zum Verarbeiten von Streams hat, habe ich einen Patch für Sie vorbereitet, damit fsockopen asynchron funktioniert. Dieser Patch ist veraltet und wird nicht in der offiziell veröffentlichten PHP-Version erscheinen. Ich habe die Implementierung der stream_socket_client()-Funktion in den Patch eingefügt, mit der Sie Ihr Skript mit
PHP5 kompatibel machen können.
PHP-Implementierung von Multi-Threading_PHP-Tutorial
Das obige ist der detaillierte Inhalt vonPHP-Multithread-PHP-fsockopen-Lösung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!