Bei Verwendung von Sockets für die Netzwerkprogrammierung in PHP sind Socket_Set_Block () und socket_set_nonblock () zwei sehr wichtige Funktionen, die Sockets steuern, um den Blockierungsmodus bzw. dem Nichtblockierungsmodus einzugeben. Viele Entwickler ignorieren jedoch einen Schlüsselpunkt, nachdem er ihn auf den Blockierungsmodus eingestellt hat:.
Dann ist die Frage: Was passiert, wenn Sie Socket_Set_Block () verwenden, aber vergessen, das Timeout festzulegen? Wird das Programm stecken bleiben? Dieser Artikel beantwortet diese Frage ausführlich.
Wenn Sie Socket_Set_Block ($ Socket) verwenden, um den Socket auf den Blockierungsmodus festzulegen, werden nachfolgende Lesen und Schreibvorgänge (z. B. Socket_Read () , socket_recv () , socket_write () usw.) blockiert und warten, wenn die Daten nicht fertig sind. Wenn Sie versuchen, eine Socket ohne Daten zu lesen, wird das Programm in dieser Codezeile stehen, bis die Daten lesbar sind oder die Verbindung nicht verbunden ist .
Dies ist in einigen Szenarien nützlich, in denen "gleichzeitige Kommunikation" erwartet wird. Sobald der externe Server langsam oder sogar dauerhaft nicht mehr reagiert (wie die Ausfallzeit von Target -Server, das Netzwerkblockieren, die Blockierung durch Firewall usw.), wird Ihr Programm dort festgehalten und kann keinen nachfolgenden Code ausführen .
Schauen wir uns ein Beispiel an:
<code> $ socket = socket_create (af_inet, sock_stream, sol_tcp); socket_set_block ($ socket); Socket_Connect ($ Socket, 'Gitbox.net', 80); Socket_Write ($ Socket, "get / http / 1.0 \ r \ nHost: gitbox.net \ r \ n \ r \ n"); $ response = socket_read ($ socket, 2048);
echo $ response;
</code>
Wenn Gitbox.net nicht erreichbar ist oder überhaupt keine Daten zurückgibt, blockiert die Linie von Code socket_read () auf unbestimmte Zeit und das Programm wird "festgefahren".
Die Hauptursache von "festgefahren" ist, dass es keine Zeitüberschreitungsgrenze gibt . Der Blockierungsmodus selbst ist kein Problem, das Problem ist, dass der Zeitüberschreitungswert in socket_set_option () nicht festgelegt ist.
PHP bietet zwei Socket -Zeitüberschreitungseinstellungen:
Zeitüberschreitung erhalten
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, ['sec'=>5, 'usec'=>0]);
Timeout senden
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, ['sec'=>5, 'usec'=>0]);
Nach dem Hinzufügen, selbst im Blockierungsmodus, warten Sie nicht auf unbegrenzt. Zum Beispiel ist das Empfangs -Zeitüberschreitend auf 5 Sekunden festgelegt. Wenn innerhalb von 5 Sekunden keine Daten empfangen werden, gibt Socket_read () false zurück und blockiert nicht für immer.
Wenn Sie vergessen, das Timeout festzulegen, gibt es mehrere potenzielle Konsequenzen:
Der Server reagiert nicht oder steckt fest, wenn es langsam ist
Der Benutzer wartet zu lange und hat eine sehr schlechte Erfahrung
Eine Blockade in einer Batch -Aufgabe bewirkt, dass die Gesamtaufgabe die Warteschlange oder sogar unterbricht.
Es ist schwierig, Probleme zu beheben, insbesondere wenn der Fehler nur auftritt, wenn das Netzwerk instabil ist
Daher sollte jeder Netzwerkbetrieb im Blockierungsmodus mit einer klaren Zeitüberschreitungseinstellung verwendet werden .
Ja, wenn Sie socket_set_block () verwenden und vergessen, das Timeout festzulegen, kann das Programm in einigen Fällen tatsächlich "abgestanden". Dies ist kein Fehler in PHP, sondern ein grundlegendes Verhalten bei der Blockierung der E/A in der Netzwerkprogrammierung. Die rationale Verwendung von Socket_Set_Option () zum Festlegen von Zeitüberschreitungen ist der Schlüssel zur Gewährleistung der Robustheit und Reaktionsfähigkeit der Programme.
Die beste Praxis ist: Solange Sie den Blockierungsmodus eingeben, stellen Sie die Zeitüberschreitung sofort fest und verlassen Sie sich nicht auf die Zuverlässigkeit des Remote -Servers. Dies ist ein grundlegendes Denken der Verteidigungsprogrammierung.