Signatur
Beschreibung
socket_set_nonblock() versetzt den übergebenen Socket in den nicht-blockierenden Modus. Im Gegensatz zum Standard-Blocking-Modus, bei dem Funktionen wie socket_read() oder socket_accept() so lange warten, bis Daten verfügbar sind, kehren diese Funktionen im Non-Blocking-Modus sofort zurück – entweder mit Daten oder mit einem Fehlercode (SOCKET_EAGAIN / SOCKET_EWOULDBLOCK), wenn keine Daten verfügbar sind.
Dieser Modus ist besonders nützlich beim Aufbau von Server-Anwendungen, die mehrere Verbindungen gleichzeitig verwalten müssen, ohne für jeden Client einen eigenen Prozess oder Thread zu benötigen. Typischerweise wird er in Kombination mit socket_select() eingesetzt, um effizient auf mehrere Sockets zu warten.
Das Gegenstück ist socket_set_block(), das den Socket wieder in den blockierenden Modus zurückversetzt. Es empfiehlt sich, den Modus bewusst zu wählen und Fehler (SOCKET_EAGAIN) korrekt zu behandeln, da sie im Non-Blocking-Modus kein eigentlicher Fehler, sondern ein normaler Betriebszustand sind.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $socket Pflicht | Socket | Eine gültige Socket-Instanz, die zuvor mit socket_create() oder socket_accept() erzeugt wurde. |
Rückgabewert
true bei Erfolg zurück. Im Fehlerfall wird false zurückgegeben; der genaue Fehlercode kann dann mit socket_last_error() abgerufen werden.Beispiele
Einfacher Non-Blocking-Server mit socket_select()
<?php
// Socket erstellen
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($server === false) {
die('socket_create() fehlgeschlagen: ' . socket_strerror(socket_last_error()));
}
// Socket an Port binden
socket_bind($server, '0.0.0.0', 8080);
socket_listen($server, 5);
// In Non-Blocking-Modus wechseln
if (!socket_set_nonblock($server)) {
die('socket_set_nonblock() fehlgeschlagen: ' . socket_strerror(socket_last_error($server)));
}
$clients = [];
echo "Server läuft im Non-Blocking-Modus auf Port 8080...\n";
for ($i = 0; $i < 10; $i++) {
// Neue Verbindung akzeptieren – kehrt sofort zurück (non-blocking)
$client = @socket_accept($server);
if ($client !== false) {
socket_set_nonblock($client);
$clients[] = $client;
echo "Neuer Client verbunden.\n";
}
// Vorhandene Clients abfragen
foreach ($clients as $key => $c) {
$data = @socket_read($c, 1024);
if ($data === false) {
// EAGAIN: Keine Daten verfügbar – kein Fehler im Non-Blocking-Modus
$errno = socket_last_error($c);
if ($errno !== SOCKET_EAGAIN && $errno !== SOCKET_EWOULDBLOCK) {
echo "Fehler bei Client: " . socket_strerror($errno) . "\n";
socket_close($c);
unset($clients[$key]);
}
} elseif ($data === '') {
// Verbindung geschlossen
socket_close($c);
unset($clients[$key]);
} else {
echo "Empfangen: $data\n";
socket_write($c, "Echo: $data");
}
}
usleep(100000); // 100 ms warten
}
socket_close($server);
Non-Blocking-Modus und anschließende Rückkehr zu Blocking
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, 'example.com', 80);
// Auf Non-Blocking umschalten
socket_set_nonblock($socket);
$result = @socket_read($socket, 512);
if ($result === false) {
$errno = socket_last_error($socket);
if ($errno === SOCKET_EAGAIN || $errno === SOCKET_EWOULDBLOCK) {
echo "Keine Daten verfügbar (Non-Blocking, kein Fehler).\n";
} else {
echo "Fehler: " . socket_strerror($errno) . "\n";
}
}
// Zurück in den Blocking-Modus
socket_set_block($socket);
$request = "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n";
socket_write($socket, $request);
$response = socket_read($socket, 2048);
echo substr($response, 0, 100) . "\n";
socket_close($socket);
// Wichtig · Fallstricke
Fehlerbehandlung: Im Non-Blocking-Modus liefern socket_read(), socket_accept() und ähnliche Funktionen false zurück, wenn gerade keine Daten verfügbar sind. Das ist kein Fehler – der Fehlercode ist dann SOCKET_EAGAIN oder SOCKET_EWOULDBLOCK. Diese Codes müssen explizit abgefangen werden, um echte Fehler von "keine Daten verfügbar" zu unterscheiden.
Kompatibilität: Ab PHP 8.0 erwartet die Funktion ein Socket-Objekt statt einer Ressource. In älteren PHP-Versionen wurde eine resource übergeben.
Empfehlung: Für komplexe Event-gesteuerte Netzwerkanwendungen empfehlen sich Bibliotheken wie ReactPHP oder Swoole, die intern ebenfalls auf Non-Blocking-Sockets aufbauen und eine abstraktere API bieten.