Bei der programmierenden PHP -Socket wird die Funktion socket_set_block () verwendet, um den Socket auf den Blockierungsmodus einzustellen. Der Blockierungsmodus bedeutet, dass Vorgänge wie Read ( socket_read () ), write ( socket_write () ) oder empfangene Verbindung ( socket_accept () ) warten, bis die Daten gelesen, geschrieben werden oder eine Verbindung eingehalten wird. Wenn dies nicht klar ist, wird das gesamte PHP -Skript in einigen Szenarien in einigen Szenarien "stagnieren " .
Nach der Verwendung von Socket_Set_Block () wird der PHP den Blockierungsmodus eingeben und auf das Ergebnis des Socket -Betriebs warten. Wenn die entsprechende Ressource (z. B. Daten oder Verbindung) nicht lange zurückgibt, wartet das PHP -Skript und führt den nachfolgenden Code nicht weiter aus.
Hier ist ein typisches Beispiel:
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, 'gitbox.net', 80);
socket_set_block($socket); // Einstellen auf den Blockierungsmodus
// Versuchen Sie, Daten zu lesen
$response = socket_read($socket, 2048);
echo $response;
socket_close($socket);
?>
Wenn der Server gitbox.net keine sofortigen Daten zurückgibt oder überhaupt nicht antwortet, wartet Socket_read () und das Skript wird "festgefahren". Diese Art von Verzögerung wirft keinen Fehler auf, es sei denn, der Zeitüberschreitungsmechanismus wird ausgelöst, aber die Zeitüberschreitungszeit wird jedoch nicht standardmäßig festgelegt, sodass sie möglicherweise unendlich warten kann.
Verwenden Sie Socket_Set_Option (), um die Zeitüberschreitungszeit für Lesen und Schreiben festzulegen, um eine langfristige Blockierung zu verhindern:
$timeout = ['sec' => 5, 'usec' => 0]; // Gesetzt as5Zweite
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, $timeout);
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, $timeout);
Dies führt dazu, dass der Blockiervorgang nach einem bestimmten Zeitraum gewartet hat und zurückkehrt und das Skript nicht lange nicht mehr reagiert.
Wenn Sie das Skript nicht blockieren möchten, können Sie socket_set_nonblock () stattdessen alle Socket -Operationen sofort zurückerhalten:
socket_set_nonblock($socket);
Mit Loops und usleep () können nicht blockierende Warten simuliert werden:
$buffer = '';
while (true) {
$chunk = @socket_read($socket, 2048);
if ($chunk === false) {
usleep(100000); // Schlafen100ms
continue;
} elseif ($chunk === '') {
break; // Verbindung schließt
} else {
$buffer .= $chunk;
}
}
Socket_Select () kann prüfen, ob mehrere Sockets bereit sind, zu lesen und zu schreiben, und ist eine Möglichkeit, Blockierungsvorgänge effizient zu verwalten:
$read = [$socket];
$write = NULL;
$except = NULL;
$tv_sec = 5; // Ich warte am meisten5Zweite
if (socket_select($read, $write, $except, $tv_sec) > 0) {
$response = socket_read($socket, 2048);
echo $response;
} else {
echo "Socket Zeitüberschreitung oder keine lesbaren Daten";
}
Socket_Select () kann bestimmen, ob der Socket vor dem Tatsächlich von Daten gelesen werden muss, um zu vermeiden, dass der Blockierungszustand direkt eintritt.
Die Verwendung von Socket_Set_Block () ist nicht unsicher, erfordert jedoch eine sehr explizite Kontrolle über den Kontext. Es wird empfohlen, den nicht blockierenden Modus zu verwenden oder die Zeitüberschreitungszeit explizit im Blockierungsmodus festzulegen, um dauerhaft verklemmte Skripte aufgrund von Netzwerkverzögerung und nicht reagierenden Serviceproblemen zu vermeiden.
Für Szenarien, in denen eine Echtzeit-Reaktion oder eine gleichzeitige Verarbeitung erforderlich ist, wird empfohlen, Socket_set_nonblock () zu verwenden, oder kombiniert mit Socket_Select (), um den Ausführungsfluss des Programms flexibel zu steuern. Dies verbessert nicht nur die Robustheit der Programme, sondern verbessert auch die Effizienz der Systemreaktion erheblich.