Heim > Backend-Entwicklung > PHP-Tutorial > PHP-Multithread-PHP-fsockopen-Lösung

PHP-Multithread-PHP-fsockopen-Lösung

不言
Freigeben: 2023-03-23 21:12:02
Original
2828 Leute haben es durchsucht

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.

Tatsächlich müssen Sie in den meisten Fällen weder Fork noch Thread verwenden und erzielen eine bessere Leistung als mit Fork oder Thread.

Angenommen, Sie möchten einen Dienst erstellen, um n laufende Server zu überprüfen, um sicherzustellen, dass sie noch normal funktionieren. Sie könnten Code wie diesen schreiben:


$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);
Nach dem Login kopieren



Es funktioniert gut, aber nach fsockopen() wird dieser Code erweitert Die Verwaltung einer großen Anzahl von Servern würde lange dauern, bis der Hostname geparst ist und eine erfolgreiche Verbindung hergestellt wird (oder um $timeout-Sekunden verzögert).

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.

Das Folgende ist die Lösung in 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";
}
Nach dem Login kopieren



Wir warten mit stream_select() Verbindungsereignisse für geöffnete Sockets. stream_select() ruft die Funktion select(2) des Systems auf, um zu funktionieren: Die ersten drei Parameter sind die Arrays von Streams, die Sie verwenden möchten, Sie können sie lesen, schreiben und Ausnahmen erhalten (jeweils für die drei Parameter). stream_select() kann auf das Eintreten eines Ereignisses warten, indem der Parameter $timeout (Sekunden) festgelegt wird. Wenn das Ereignis eintritt, werden die entsprechenden Socket-Daten in die von Ihnen übergebenen Parameter geschrieben.

Das Folgende ist die Implementierung von PHP 4.1.0 und höher. Wenn Sie beim Kompilieren von PHP Sockets (ext/sockets) unterstützt haben, können Sie ähnlichen Code wie oben verwenden, müssen nur die oben genannten Streams/ ändern. Dateisystem Die Funktionen der Funktion werden mithilfe der Funktion ext/sockets implementiert. Der Hauptunterschied besteht darin, dass wir anstelle von

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;
}
Nach dem Login kopieren


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.

Verwandte Empfehlungen:

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!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage