Start · Sprachen · PHP · Referenz · EventListener

EventListener

Klasse

Repräsentiert einen Connection-Listener, der auf eingehende Netzwerkverbindungen wartet und diese über die <code>Event</code>-Erweiterung verwaltet.

Kategorie: io

Signatur

class EventListener

Beschreibung

EventListener ist Teil der Event-Erweiterung (basierend auf libevent) und kapselt einen TCP- oder Unix-Socket-Listener. Mit einem EventListener-Objekt kann eine Anwendung auf einem bestimmten Port oder Pfad auf eingehende Verbindungen warten, ohne blockierend zu arbeiten.

Sobald eine neue Verbindung akzeptiert wurde, ruft EventListener automatisch eine Callback-Funktion auf, die den zugehörigen EventBase-Kontext und den Dateideskriptor der neuen Verbindung erhält. Dies ermöglicht das effiziente Erstellen von nicht-blockierenden, ereignisgesteuerten Servern in PHP.

Typische Einsatzgebiete sind asynchrone TCP-Server, Chat-Server, Proxy-Dienste oder jede andere Anwendung, bei der viele gleichzeitige Verbindungen ohne den Overhead klassischer Thread-Modelle verarbeitet werden sollen.

  • Erfordert die installierte event-PECL-Erweiterung.
  • Arbeitet eng mit EventBase und EventConfig zusammen.
  • Unterstützt sowohl IPv4/IPv6-TCP-Sockets als auch Unix-Domain-Sockets.

Parameter

Name Typ Default Beschreibung
$base Pflicht EventBase Die EventBase-Instanz, die als Ereignisschleife für diesen Listener verwendet wird.
$cb Pflicht callable Callback-Funktion, die aufgerufen wird, sobald eine neue Verbindung akzeptiert wurde. Signatur: function(EventListener $listener, mixed $fd, array $address, mixed $arg): void.
$data mixed null Beliebige benutzerdefinierte Daten, die beim Aufruf des Callbacks als $arg übergeben werden.
$flags Pflicht int Bitmaske aus EventListener::OPT_*-Konstanten, z. B. EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE, die das Verhalten des Listeners steuern.
$backlog Pflicht int Maximale Anzahl ausstehender Verbindungen in der Warteschlange. Ein Wert von -1 überlässt die Wahl dem Betriebssystem.
$target Pflicht mixed Adresse oder Dateideskriptor, auf dem gelauscht werden soll. Kann ein String wie "0.0.0.0:8080", ein Unix-Socket-Pfad "unix:/tmp/app.sock" oder ein bereits vorhandener Socket-Ressource-Handle sein.

Rückgabewert

Typ

Beispiele

Einfacher nicht-blockierender TCP-Echo-Server

<?php
// Voraussetzung: PECL-Erweiterung 'event' muss installiert sein

$base = new EventBase();

$listener = new EventListener(
    $base,
    function (EventListener $listener, $fd, array $address, $ctx) {
        // Neue Verbindung wurde akzeptiert
        $base = $listener->getBase();

        // BufferedEvent für den Client erstellen
        $bev = new EventBufferEvent(
            $base,
            $fd,
            EventBufferEvent::OPT_CLOSE_ON_FREE
        );

        $bev->setCallbacks(
            function (EventBufferEvent $bev) {
                // Daten einlesen und zurückspiegeln (Echo)
                $buf  = $bev->getInput();
                $data = $buf->read($buf->length);
                $bev->write($data);
            },
            null,
            function (EventBufferEvent $bev, $events) {
                if ($events & (EventBufferEvent::EOF | EventBufferEvent::ERROR)) {
                    $bev->free();
                }
            }
        );

        $bev->enable(Event::READ | Event::WRITE);
    },
    null,
    EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE,
    -1,
    '0.0.0.0:9000'
);

if (!$listener) {
    exit('Listener konnte nicht erstellt werden.' . PHP_EOL);
}

echo 'Echo-Server lauscht auf Port 9000 ...' . PHP_EOL;
$base->dispatch(); // Ereignisschleife starten
Echo-Server lauscht auf Port 9000 ...

Listener deaktivieren und wieder aktivieren

<?php
$base = new EventBase();

$listener = new EventListener(
    $base,
    function (EventListener $l, $fd, $addr, $data) {
        echo 'Verbindung von ' . $addr[0] . ':' . $addr[1] . PHP_EOL;
    },
    null,
    EventListener::OPT_CLOSE_ON_FREE | EventListener::OPT_REUSEABLE,
    -1,
    '127.0.0.1:9090'
);

// Listener vorübergehend deaktivieren
$listener->disable();
echo 'Listener deaktiviert.' . PHP_EOL;

// Listener wieder aktivieren
$listener->enable();
echo 'Listener wieder aktiv.' . PHP_EOL;

// Fehler-Callback setzen
$listener->setErrorCallback(function (EventListener $l, $data) {
    $errorCode = EventUtil::getLastSocketErrno();
    echo 'Listener-Fehler: ' . $errorCode . PHP_EOL;
    $l->getBase()->exit();
});

$base->dispatch();
Listener deaktiviert. Listener wieder aktiv.

// Wichtig · Fallstricke

Erweiterungs-Abhängigkeit: EventListener ist keine PHP-Kern-Klasse, sondern Teil der PECL-Erweiterung event. Diese muss separat installiert werden (pecl install event) und ist nicht standardmäßig vorhanden.

Ressourcen-Verwaltung: Mit dem Flag EventListener::OPT_CLOSE_ON_FREE wird der zugrundeliegende Socket automatisch geschlossen, wenn das EventListener-Objekt freigegeben wird. Ohne dieses Flag muss der Socket manuell geschlossen werden, um Ressourcenlecks zu vermeiden.

Sicherheit: Lauscht der Server auf einer öffentlich erreichbaren Adresse, sollte unbedingt eine Verbindungslimitierung und Eingabevalidierung im Callback implementiert werden, um Denial-of-Service-Angriffe zu verhindern. Der backlog-Parameter beeinflusst, wie viele Verbindungen im Kernel-Puffer warten dürfen, bevor neue abgelehnt werden.

Thread-Sicherheit: Die Event-Erweiterung ist nicht thread-sicher. Jeder Thread muss seine eigene EventBase-Instanz verwenden.