Aktueller Standort: Startseite> Neueste Artikel> Warum ist das Programm noch nicht blockiert, nachdem Socket_Set_Block festgelegt wurde?

Warum ist das Programm noch nicht blockiert, nachdem Socket_Set_Block festgelegt wurde?

gitbox 2025-05-29

Warum erscheint das PHP-Programm nach dem Aufrufen der Funktion Socket_Set_Block immer noch im nicht blockierenden Modus?

Bei der Verwendung von Socket -Programmierungen in PHP wird die Funktion Socket_Set_Block normalerweise verwendet, um den Socket auf den Blockierungsmodus einzustellen. Es wird erwartet, dass nachfolgende Lese- und Schreibvorgänge vor der fortgesetzten Ausführung auf Datenabschluss "warten" können. Viele Entwickler werden jedoch auf das Problem stoßen: Nach dem Aufrufen von Socket_Set_Block scheint das Programm immer noch nicht blockiert zu sein, und es wird nicht warten, dass das Lesen und Schreiben nicht warten, sondern sofort zurückkehren. Warum ist das? In diesem Artikel wird die Gründe eingehend analysiert und entsprechende Lösungen angeben.

1. Die Funktionen und Einschränkungen von Socket_Set_Block

Die Funktion von Socket_Set_Block besteht darin, einen Socket auf den Blockierungsmodus festzulegen, dh beim Aufrufen von Lese- und Schreibfunktionen, wenn keine Daten gelesen oder geschrieben werden müssen, wird der Anruf blockiert, bis Daten oder Zeitablauf vorhanden sind. Seine Funktionssignatur ist:

 bool socket_set_block ( resource $socket )

Rückgabe true , wenn der Anruf erfolgreich ist, andernfalls geben Sie false zurück.

Es ist jedoch wichtig zu beachten:

  • Socket_Set_Block ist ein Blockierungsmodus für die zugrunde liegende Socket -Ressource, und sein Effekt hängt vom spezifischen Status der Socket ab.

  • Wenn sich der Socket bereits im nicht blockierenden Modus befindet (z. B. wurde schon einmal Socket_set_nonblock aufgerufen), sollte das Blockieren nach dem Aufrufen von Socket_Set_Block wieder aufgenommen werden.

  • Wenn sich der Sockel selbst jedoch in einem speziellen Zustand befindet (z. B. bereits verbunden oder ein System zugrunde liegender Zustand), wird die Festlegung des Blockierungsmodus möglicherweise nicht wirksam.

2. Warum erscheint das Programm noch im nicht blockierenden Modus?

  1. Der zugrunde liegende Socket wird durch einen anderen Code auf einen nicht blockierenden Zustand zurückgesetzt

Es kann im Programm andere Code oder Frameworks geben, die mit den Socket -Einstellungen in Konflikt stehen. Vor dem Aufrufen von Socket_Set_Block können einige Bibliotheken oder Middleware beispielsweise Socket_Set_NonBlock aufrufen, und selbst der zugrunde liegende Systemaufruf ändert die Socket -Eigenschaften, was zu ungültigen nachfolgenden Aufrufen führt.

  1. Die Sockelverbindung befindet sich in einem asynchronen oder Timeout -Zustand

In einigen Betriebssystemen oder PHP -Versionen wird die Einstellung des Blockierungsmodus des Sockets möglicherweise nicht wirksam, wenn sich die Steckdose in Verbindung befindet oder ein Zeitüberschreitungsmodell erfolgt. Zum Beispiel:

  • Das Aufrufen von Lese- und Schreibvorgängen blockiert nicht, wenn die Verbindung nicht abgeschlossen wurde.

  • Nicht standardmäßige Socket-Typen (z. B. Unix Domain Socket, SSL Socket) unterstützen den Blockierungsmodus inkonsistent.

  1. PHP -Version und Betriebssystemkompatibilitätsprobleme

Verschiedene Versionen von PHP können sich in der zugrunde liegenden Implementierung von Socket -Funktionen unterscheiden. Insbesondere das Verhalten von Windows- und Linux -Plattformen ist ebenfalls unterschiedlich.

  1. Falsche Anrufbeschaffung

Wenn Socket_Set_Block zuerst aufgerufen wird, andere Funktionen, die Blockier-/Nicht-Blockierstatus festlegen, werden später aufgerufen, die Statuswechsel ist ungültig.

  1. Die im Code verwendeten Funktionen sind selbst nicht blockierend ausgelegt

Beispielsweise wirkt sich die Leistung des Programms auf die Leistung des Socket_Select oder die Verwendung von nicht blockierenden Stream-Betriebsfunktionen, selbst wenn sich der Socket in einem Blockierungszustand befindet.

3. Wie kann man Socket_Set_Block richtig verwenden?

  • Nennen Sie es nur einmal und an einem angemessenen Ort

Das Aufrufen von Socket_Set_Block sollte nach der erfolgreichen Erstellung und Angeschlossenen der Socket platziert werden, und stellen Sie sicher, dass kein nachfolgender Code diese Einstellung überschreibt.

 $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, "gitbox.net", 80);
socket_set_block($socket);
  • Kombiniert mit Fehlerprüfung

Überprüfen Sie, ob der Funktionsaufruf true zurückgibt, und prüfen Sie, ob ein System- oder Socket -Fehler vorliegt.

 if (!socket_set_block($socket)) {
    $errorcode = socket_last_error($socket);
    $errormsg = socket_strerror($errorcode);
    echo "Das Blockieren des Blockierens fehlgeschlagen: [$errorcode] $errormsg\n";
}
  • Vermeiden Sie es, nicht blockierende Funktionen zum Mischen zu verwenden

Mischen Sie nicht socket_set_block und socket_set_nonblock, um Statusverwirrung zu vermeiden.

Wenn Sie den Stream -Kapselungsbuchse von PHP verwenden, können Sie Stream_Set_Blocking verwenden, um den Blockierungsmodus zu steuern.

 $stream = stream_socket_client("tcp://gitbox.net:80", $errno, $errstr, 30);
stream_set_blocking($stream, true);

4. Beispielcode

Das folgende Beispiel zeigt, wie man einen blockierenden Socket ordnungsgemäß eingerichtet und eine HTTP -Anforderung sendet:

 <?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
    die("erstellenSocketscheitern: " . socket_strerror(socket_last_error()) . "\n");
}

$result = socket_connect($socket, "gitbox.net", 80);
if ($result === false) {
    die("连接scheitern: " . socket_strerror(socket_last_error($socket)) . "\n");
}

// Setzen Sie den Blockierungsmodus
if (!socket_set_block($socket)) {
    die("Das Blockieren des Blockierens fehlgeschlagen: " . socket_strerror(socket_last_error($socket)) . "\n");
}

$request = "GET / HTTP/1.1\r\nHost: gitbox.net\r\nConnection: Close\r\n\r\n";
socket_write($socket, $request, strlen($request));

// Blöcke beim Lesen von Daten,Bis der Inhalt empfangen wird oder die Verbindung geschlossen ist
$response = '';
while ($out = socket_read($socket, 2048)) {
    $response .= $out;
}

echo $response;

socket_close($socket);

5. Zusammenfassung

  • Die Funktion von Socket_Set_Block besteht darin, Socket auf Block zu setzen, ist jedoch nicht allmächtig und wird von verschiedenen Faktoren wie dem Socket -Status selbst, dem Betriebssystem, der PHP -Version und der Aufrufreihenfolge beeinflusst.

  • Das Aufrufen von Socket_Set_Block zeigt immer noch nicht blockierende, normalerweise weil der Status von einem anderen Code abgedeckt ist, der Verbindungsstatus besonders oder die zugrunde liegende Implementierung unterschiedlich ist.

  • Der korrekte Ansatz besteht darin, den Blockierungs-Setup-Prozess der Socket strikt zu steuern, um zu vermeiden, dass Aufrufe zum Blockieren und nicht blockierenden Setup-Funktionen gemischt werden.

  • Verstehen Sie die Unterschiede in der zugrunde liegenden Socket- und PHP -Umgebung und kombinieren Sie Probleme mit der Debug -Informationspositionierung.

Wenn Sie diese wichtigen Punkte beherrschen, können Sie ein stabileres Steckdosenblockierungsverhalten in PHP kontrollierter steuern und eine unerwartete asynchrone Leistung vermeiden.