Signatur
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
EventBaseundEventConfigzusammen. - 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
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
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();
// 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.