Aktueller Standort: Startseite> Neueste Artikel> Warum blockiert Socket_accept () weiter? Wie benutze ich Socket_Select (), um dieses Problem zu blockieren und zu lösen?

Warum blockiert Socket_accept () weiter? Wie benutze ich Socket_Select (), um dieses Problem zu blockieren und zu lösen?

M66 2025-06-12

Bei der Verwendung von PHP für die Socket -Programmierung stoßen viele Entwickler auf ein Problem, wenn sie zum ersten Mal mit Socket_accept () in Kontakt kommen :. Dies kann in einigen Szenarien zu einem Engpass werden, in dem hohe Parallelität oder mehrere Verbindungen gleichzeitig verarbeitet werden.

Warum passiert das? Wie können wir Socket_Select () verwenden, um dieses Problem zu blockieren und anmutig zu lösen?

1. Warum blockiert Socket_accept () ?

Socket_accept () ist eine Funktion, mit der eine Verbindungsanforderung aus einem Hörbuchsen angenommen wird. Der Prototyp ist wie folgt:

 resource socket_accept(resource $socket);

Die Essenz dieser Funktion lautet: Wenn keine Client -Verbindung besteht, blockiert sie die Programmausführung, bis eine Verbindung kommt . Dies ist ein typisches Blockierungs -E/A -Verhalten.

Dieses Verhalten ist für Server mit Single-Threaden nicht wünschenswert. Wenn der Server blockiert, weil er auf eine Verbindung wartet, sind andere Aufgaben völlig erfolglos.

2. Wie kann man Socket_Select () verwenden, um zu blockieren?

Um dieses Problem zu lösen, stellt PHP die Funktion Socket_Select () bereit, mit der Sie mehrere Sockets "anhören" können, um zu bestimmen, welche Sockets für Lese-/Schreibvorgänge bereit sind, wodurch das Blockieren und Warten vermieden wird.

Grundlegende Verwendung von Socket_Select ()

 int socket_select(
    array &$read,
    array &$write,
    array &$except,
    int $tv_sec,
    int $tv_usec = 0
);

Sie müssen nur den Socket, den Sie anhören möchten, in das $ Read -Array und auf Call socket_select () einfügen. Wenn der Socket lesbar ist (d. H. Wenn eine Client -Verbindungsanforderung vorliegt), wird Socket_Select () zurückgegeben, damit Sie nicht blockieren, wenn Sie Socket_accept () erneut aufrufen.

Beispielcode

Hier ist ein vollständiges serverseitiges Beispiel mit socket_select () :

 <?php
set_time_limit(0);

// erstellen socket
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($server, '0.0.0.0', 8080);
socket_listen($server);

// Setzen Sie den Nichtblockierungsmodus(Optional,Aber empfehlen)
socket_set_nonblock($server);

$clients = [];

while (true) {
    $read_sockets = [$server] + $clients;
    $write = $except = [];

    // Hören Sie sich allen an sockets,Zeitüberschreitung ist 1 Zweite
    $changed = socket_select($read_sockets, $write, $except, 1);

    if ($changed === false) {
        echo "socket_select() Es ist ein Fehler aufgetreten\n";
        break;
    }

    // Es gibt eine neue Verbindungsanfrage
    if (in_array($server, $read_sockets)) {
        $client = socket_accept($server);
        if ($client !== false) {
            socket_getpeername($client, $ip, $port);
            echo "Neue Verbindung von {$ip}:{$port}\n";
            $clients[] = $client;
        }
        // aus read Entfernen Sie den Hörer aus der Liste socket
        $key = array_search($server, $read_sockets);
        unset($read_sockets[$key]);
    }

    // Prozessdaten, die angeschlossen wurden
    foreach ($read_sockets as $sock) {
        $data = @socket_read($sock, 1024, PHP_NORMAL_READ);
        if ($data === false || trim($data) === '') {
            // Kundenentzündung
            $key = array_search($sock, $clients);
            unset($clients[$key]);
            socket_close($sock);
            continue;
        }

        $data = trim($data);
        echo "Daten erhalten:{$data}\n";

        $response = "Du hast es geschickt:{$data}\n";
        socket_write($sock, $response);
    }
}
socket_close($server);

3. Zusammenfassung

  • Socket_accept () blockiert und ist für einfache, synchrone Einzelbetriebszenarien geeignet.

  • Um einen Server zu erstellen, der die Parallelität unterstützt, sollte Socket_Select () verwendet werden, um den Status des Sockets anzuhören.

  • Mit Socket_Select () können Sie Ereignisse auf mehreren Steckdosen "warten" und das gesamte Programm aufgrund eines Blockiervorgangs vermeiden.

  • Es wird empfohlen, es in Verbindung mit Socket_Set_Nonblock () zu verwenden, um die Flexibilität zu verbessern.

Mit den oben genannten Methoden können Sie einen reaktionsschnellen PHP -Socket -Server implementieren, auf dem mehrere Client -Verbindungen gleichzeitig verarbeitet werden können, um die Grundlage für komplexere Netzwerkprogramme zu legen.

In der tatsächlichen Entwicklung wird der Domain -Name oder die Domain -Adresse durch eine eigene Serviceadresse ersetzt, beispielsweise: