Start · Sprachen · PHP · Referenz · EventBufferEvent

EventBufferEvent

Klasse

Repräsentiert ein Libevent-Buffer-Event für asynchrones, gepuffertes I/O mit Lese- und Schreib-Callbacks.

seit PHP 1.2.6 Kategorie: io

Signatur

class EventBufferEvent

Beschreibung

EventBufferEvent ist Teil der Event-Extension und kapselt Libevents bufferevent-API. Ein Buffer-Event verwaltet automatisch einen Eingabe- und einen Ausgabepuffer (EventBuffer) und ruft benutzerdefinierte Callbacks auf, wenn Daten gelesen oder geschrieben werden können oder ein Fehler auftritt.

Im Gegensatz zu einfachen Event-Objekten übernimmt EventBufferEvent das Puffern vollständig: Eingehende Daten werden in einen internen Lese-Puffer geschrieben und stehen dann asynchron zur Verfügung; ausgehende Daten werden in einen Schreib-Puffer gelegt und bei Gelegenheit gesendet. Das reduziert den Boilerplate-Code für typische TCP-Client- und -Server-Implementierungen erheblich.

Typische Einsatzgebiete sind nicht-blockierende TCP-Verbindungen (Client und Server), SSL/TLS-gesicherte Streams (über EventBufferEvent::sslFilter() oder EventBufferEvent::sslSocket()), sowie Pipe-basierte IPC. Der Entwickler definiert Callbacks für Lesen, Schreiben und Ereignisse (Verbindungsaufbau, -trennung, Fehler) und delegiert den Rest an die Event-Schleife.

Wichtig: EventBufferEvent-Objekte müssen immer innerhalb einer laufenden EventBase-Schleife verwendet werden und sollten nicht über Prozesgrenzen hinweg geteilt werden.

Parameter

Name Typ Default Beschreibung
$base Pflicht EventBase Die EventBase-Instanz, an die dieses Buffer-Event gebunden wird.
$socket mixed null Ein Stream-Resource-Handle, eine Socket-Resource oder ein Integer (Socket-Deskriptor). Kann null sein, wenn der Socket später über EventBufferEvent::connect() gesetzt wird.
$options int 0 Bitmaske aus EventBufferEvent::OPT_*-Konstanten, z. B. EventBufferEvent::OPT_CLOSE_ON_FREE oder EventBufferEvent::OPT_THREADSAFE.
$readcb callable|null null Callback, der aufgerufen wird, wenn Daten im Lese-Puffer verfügbar sind. Signatur: function(EventBufferEvent $bev, mixed $arg): void.
$writecb callable|null null Callback, der aufgerufen wird, wenn der Schreib-Puffer unter den Wasserzeichenwert fällt (d. h. Daten wurden gesendet). Selbe Signatur wie readcb.
$eventcb callable|null null Callback für Verbindungsereignisse (Verbindungsaufbau, -trennung, Fehler). Signatur: function(EventBufferEvent $bev, int $events, mixed $arg): void. $events ist eine Bitmaske aus EventBufferEvent::EOF, EventBufferEvent::ERROR, EventBufferEvent::CONNECTED usw.
$arg mixed null Beliebiges Argument, das an alle Callbacks als letzten Parameter weitergegeben wird.

Beispiele

Einfacher nicht-blockierender TCP-Echo-Client

<?php
$base = new EventBase();

$bev = new EventBufferEvent(
    $base,
    null,
    EventBufferEvent::OPT_CLOSE_ON_FREE,
    function (EventBufferEvent $bev, $arg) {
        // Lese-Callback: alle verfügbaren Daten aus dem Puffer holen
        $data = $bev->getInput()->read(1024);
        echo "Empfangen: " . $data . PHP_EOL;
    },
    null,
    function (EventBufferEvent $bev, int $events, $arg) use ($base) {
        if ($events & EventBufferEvent::CONNECTED) {
            echo "Verbunden!" . PHP_EOL;
            // Nachricht senden
            $bev->write("Hello, Server!\n");
        } elseif ($events & (EventBufferEvent::ERROR | EventBufferEvent::EOF)) {
            echo "Verbindungsfehler oder EOF" . PHP_EOL;
            $base->exit();
        }
    }
);

$bev->enable(Event::READ | Event::WRITE);
$bev->connect("127.0.0.1", 12345);

$base->dispatch();
Verbunden! Empfangen: Hello, Server!

SSL/TLS-Verbindung mit EventBufferEvent::sslSocket()

<?php
$base  = new EventBase();
$ctx   = new EventSslContext(
    EventSslContext::TLS_CLIENT_METHOD,
    [
        EventSslContext::OPT_VERIFY_PEER => false,
    ]
);

$bev = EventBufferEvent::sslSocket(
    $base,
    null,
    $ctx,
    EventBufferEvent::SSL_CONNECTING,
    EventBufferEvent::OPT_CLOSE_ON_FREE
);

$bev->setCallbacks(
    function (EventBufferEvent $bev) {
        echo $bev->getInput()->read(4096);
    },
    null,
    function (EventBufferEvent $bev, int $events) use ($base) {
        if ($events & EventBufferEvent::CONNECTED) {
            // HTTP-Anfrage über TLS senden
            $bev->write("GET / HTTP/1.0\r\nHost: example.com\r\n\r\n");
        } elseif ($events & EventBufferEvent::EOF) {
            $base->exit();
        }
    }
);

$bev->enable(Event::READ | Event::WRITE);
$bev->connectHost($base->getDnsBase(), 'example.com', 443);
$base->dispatch();

// Wichtig · Fallstricke

Wasserzeichen (Watermarks): Mit EventBufferEvent::setWatermark() lässt sich steuern, ab welcher Datenmenge der Lese-Callback ausgelöst wird. Das verhindert unnötig häufige Callbacks bei kleinen Datenpaketen.

Thread-Sicherheit: Bei Verwendung in mehreren Threads muss die Option EventBufferEvent::OPT_THREADSAFE gesetzt und EventBase mit EventConfig::FEATURE_FDS konfiguriert werden.

Ressourcen-Verwaltung: Ein EventBufferEvent-Objekt gibt den zugehörigen Socket nur dann automatisch frei, wenn EventBufferEvent::OPT_CLOSE_ON_FREE gesetzt ist. Andernfalls muss der Socket manuell geschlossen werden.

Achtung bei SSL: Die SSL-Methoden (sslSocket, sslFilter) erfordern, dass PHP mit OpenSSL-Unterstützung kompiliert und die Event-Extension mit SSL-Unterstützung gebaut wurde.