Start · Sprachen · PHP · Referenz · EvIo

EvIo

Klasse

Überwacht die Bereitschaft eines Dateideskriptors oder Sockets für Lese- oder Schreiboperationen innerhalb der <code>Ev</code>-Ereignisschleife.

seit PHP 5.4.0 Kategorie: io

Signatur

class EvIo extends EvWatcher

Beschreibung

EvIo ist ein Watcher der PECL-Erweiterung ev und benachrichtigt die Anwendung, sobald ein Dateideskriptor oder Socket zum Lesen (Ev::READ) oder Schreiben (Ev::WRITE) bereit ist. Dadurch lassen sich nicht-blockierende I/O-Operationen effizient umsetzen, ohne dauerhaft auf Daten pollen zu müssen.

Typische Einsatzgebiete sind asynchrone Netzwerkserver, Event-getriebene Clients oder generell jede Situation, in der mehrere Verbindungen gleichzeitig ohne Threads verwaltet werden sollen. EvIo arbeitet dabei eng mit der EvLoop-Instanz oder der globalen Standard-Loop zusammen.

Der Watcher wird mit einem Dateideskriptor (z. B. einer Stream-Ressource, die über stream_socket_server() oder socket_create() erzeugt wurde), einem Ereignis-Bitfeld (Ev::READ, Ev::WRITE oder deren OR-Verknüpfung) und einem Callback instanziiert. Sobald das überwachte Ereignis eintritt, ruft die Ereignisschleife den Callback auf.

Wichtig: EvIo-Watcher reagieren auf Bereitschaft (readiness), nicht auf Abschluss; der eigentliche Lese- bzw. Schreibvorgang muss im Callback selbst durchgeführt werden. Für korrekte Funktion sollte der Deskriptor auf nicht-blockierend (stream_set_blocking($fd, false)) gesetzt sein.

Parameter

Name Typ Default Beschreibung
$fd Pflicht mixed Der zu überwachende Dateideskriptor: eine PHP-Stream-Ressource, eine Socket-Ressource oder eine ganze Zahl (roher Dateideskriptor). Muss für nicht-blockierende Nutzung vorbereitet sein.
$events Pflicht int Bitmaske der zu überwachenden Ereignisse: Ev::READ, Ev::WRITE oder Ev::READ | Ev::WRITE.
$callback Pflicht callable Callback-Funktion, die aufgerufen wird, wenn das Ereignis eintritt. Signatur: function(EvIo $watcher, int $revents): void.
$data mixed null Beliebige Benutzerdaten, die dem Watcher zugeordnet und über $watcher->data im Callback abrufbar sind.
$priority int 0 Priorität des Watchers. Höhere Werte bedeuten höhere Priorität. Erlaubter Bereich: Ev::MINPRI bis Ev::MAXPRI.

Beispiele

Nicht-blockierender TCP-Server mit EvIo

<?php
// Einfacher Echo-Server mit ev-Ereignisschleife
$server = stream_socket_server('tcp://127.0.0.1:9000', $errno, $errstr);
if (!$server) {
    die("Server konnte nicht gestartet werden: $errstr ($errno)\n");
}
stream_set_blocking($server, false);

// Watcher für eingehende Verbindungen
$acceptWatcher = new EvIo($server, Ev::READ, function ($watcher, $revents) use ($server) {
    $client = stream_socket_accept($server, 0);
    if (!$client) {
        return;
    }
    stream_set_blocking($client, false);

    // Watcher für Lesevorgänge auf dem Client-Socket
    $readWatcher = new EvIo($client, Ev::READ, function ($w, $rev) use ($client, &$readWatcher) {
        $data = fread($client, 1024);
        if ($data === '' || $data === false) {
            $readWatcher->stop();
            fclose($client);
            return;
        }
        // Echo zurück
        fwrite($client, $data);
    });
});

echo "Server lauscht auf 127.0.0.1:9000 ...\n";
Ev::run();
Server lauscht auf 127.0.0.1:9000 ...

EvIo zum Überwachen von STDIN

<?php
// Liest Zeilen von STDIN asynchron, bis 'quit' eingegeben wird
stream_set_blocking(STDIN, false);

$stdinWatcher = new EvIo(STDIN, Ev::READ, function ($watcher, $revents) {
    $line = rtrim(fgets(STDIN));
    if ($line === false || $line === '') {
        return;
    }
    echo "Eingabe empfangen: $line\n";
    if ($line === 'quit') {
        $watcher->stop();
        Ev::stop();
    }
});

Ev::run();

// Wichtig · Fallstricke

Nicht-blockierender Modus: Der überwachte Dateideskriptor sollte unbedingt auf nicht-blockierend gesetzt werden (stream_set_blocking($fd, false)), da EvIo nur die Bereitschaft signalisiert, nicht aber garantiert, dass eine vollständige Datenmenge verfügbar ist.

Lebensdauer des Watchers: Solange eine EvIo-Instanz aktiv ist (d. h. nicht gestoppt oder zerstört wurde), hält sie intern eine Referenz auf den Dateideskriptor. Ein explizites $watcher->stop() ist empfehlenswert, bevor der zugehörige Deskriptor geschlossen wird, um Ressourcenlecks zu vermeiden.

Plattformabhängigkeit: Unter Windows sind EvIo-Watcher nur mit Sockets nutzbar; reguläre Datei-Handles werden dort von libev nicht unterstützt.

Verfügbarkeit: EvIo setzt die PECL-Erweiterung ev voraus, die nicht zum PHP-Kern gehört und separat installiert werden muss (pecl install ev).