Start · Sprachen · PHP · Referenz · Swoole\Coroutine\Client

Swoole\Coroutine\Client

Klasse

Stellt eine koroutinenfähige TCP/UDP-Client-Verbindung für nicht-blockierende Netzwerkkommunikation innerhalb von Swoole-Koroutinen bereit.

seit PHP 4.0.0 Kategorie: misc

Signatur

class Swoole\Coroutine\Client

Beschreibung

Swoole\Coroutine\Client ist ein asynchroner Netzwerk-Client, der innerhalb von Swoole-Koroutinen verwendet wird und blockierende Netzwerkoperationen (Verbinden, Senden, Empfangen) automatisch in nicht-blockierende, koroutinenfreundliche Aufrufe umwandelt. Während eine Operation wartet (z. B. auf eine Serverantwort), gibt die Koroutine die Kontrolle ab, sodass andere Koroutinen ausgeführt werden können.

Der Client unterstützt die Protokolle TCP (SWOOLE_SOCK_TCP), UDP (SWOOLE_SOCK_UDP), TCP6 (SWOOLE_SOCK_TCP6) und UDP6 (SWOOLE_SOCK_UDP6) sowie Unix-Domain-Sockets. Er eignet sich besonders für Dienste, die viele gleichzeitige Verbindungen zu externen Servern (z. B. Datenbanken, APIs, Caches) aufbauen müssen, ohne den gesamten Prozess zu blockieren.

Typische Verwendungsszenarien sind HTTP-Clients, Datenbank-Proxies, Microservice-Kommunikation und alle Situationen, in denen klassisches Socket-Programmieren im synchronen Stil innerhalb einer hochperformanten, koroutinenbasierten Anwendung gewünscht wird. Der Programmcode liest sich dabei wie synchrones PHP, arbeitet aber vollständig nicht-blockierend.

Instanzen dieses Clients dürfen nur innerhalb einer Koroutine erzeugt und verwendet werden. Außerhalb einer Swoole-Koroutine (z. B. im normalen PHP-Skript ohne Server-Kontext) ist das Verhalten undefiniert.

Parameter

Name Typ Default Beschreibung
$type Pflicht int Gibt den Socket-Typ an. Mögliche Werte: SWOOLE_SOCK_TCP, SWOOLE_SOCK_TCP6, SWOOLE_SOCK_UDP, SWOOLE_SOCK_UDP6, SWOOLE_SOCK_UNIX_STREAM oder SWOOLE_SOCK_UNIX_DGRAM. Für verschlüsselte Verbindungen kann SWOOLE_SOCK_TCP | SWOOLE_SSL übergeben werden.

Beispiele

Einfache TCP-Verbindung zu einem Echo-Server

<?php
use Swoole\Coroutine;
use Swoole\Coroutine\Client;

Coroutine\run(function () {
    $client = new Client(SWOOLE_SOCK_TCP);

    // Verbindungsaufbau (nicht-blockierend dank Koroutine)
    if (!$client->connect('127.0.0.1', 9501, 1.0)) {
        echo 'Verbindung fehlgeschlagen: ' . $client->errCode . PHP_EOL;
        return;
    }

    // Daten senden
    $client->send('Hallo, Server!');

    // Antwort empfangen (wartet nicht-blockierend)
    $response = $client->recv();
    echo 'Antwort vom Server: ' . $response . PHP_EOL;

    $client->close();
});
Antwort vom Server: Hallo, Server!

Mehrere gleichzeitige HTTP-Anfragen mit Koroutinen

<?php
use Swoole\Coroutine;
use Swoole\Coroutine\Client;

Coroutine\run(function () {
    $urls = [
        ['host' => 'httpbin.org', 'path' => '/get?foo=bar'],
        ['host' => 'httpbin.org', 'path' => '/get?hello=world'],
    ];

    $waitGroup = new Coroutine\WaitGroup();
    $results = [];

    foreach ($urls as $i => $url) {
        $waitGroup->add();
        Coroutine::create(function () use ($url, $i, $waitGroup, &$results) {
            $client = new Client(SWOOLE_SOCK_TCP);
            $client->set(['timeout' => 5]);

            if ($client->connect($url['host'], 80, 5)) {
                $request  = "GET {$url['path']} HTTP/1.1\r\n";
                $request .= "Host: {$url['host']}\r\n";
                $request .= "Connection: close\r\n\r\n";
                $client->send($request);

                $response = '';
                while (($chunk = $client->recv()) !== false && $chunk !== '') {
                    $response .= $chunk;
                }
                $client->close();
                $results[$i] = substr($response, 0, 120) . '...';
            } else {
                $results[$i] = 'Fehler: ' . $client->errCode;
            }
            $waitGroup->done();
        });
    }

    $waitGroup->wait();

    foreach ($results as $idx => $res) {
        echo "Ergebnis #{$idx}: {$res}" . PHP_EOL;
    }
});
Ergebnis #0: HTTP/1.1 200 OK... Ergebnis #1: HTTP/1.1 200 OK...

SSL/TLS-Verbindung zu einem HTTPS-Endpunkt

<?php
use Swoole\Coroutine;
use Swoole\Coroutine\Client;

Coroutine\run(function () {
    // SWOOLE_SOCK_TCP | SWOOLE_SSL aktiviert TLS
    $client = new Client(SWOOLE_SOCK_TCP | SWOOLE_SSL);
    $client->set([
        'ssl_verify_peer' => true,
        'ssl_cafile'      => '/etc/ssl/certs/ca-certificates.crt',
    ]);

    if (!$client->connect('example.com', 443, 3.0)) {
        echo 'TLS-Verbindung fehlgeschlagen: ' . $client->errMsg . PHP_EOL;
        return;
    }

    $client->send("GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n");
    $response = $client->recv();
    echo substr($response, 0, 200) . PHP_EOL;
    $client->close();
});
HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 ...

// Wichtig · Fallstricke

Nur innerhalb von Koroutinen verwenden: Swoole\Coroutine\Client darf ausschließlich innerhalb einer laufenden Koroutine instanziiert und verwendet werden. Andernfalls kommt es zu einem fatalen Fehler oder undefiniertem Verhalten.

  • Timeouts: Der dritte Parameter von connect() sowie die Option timeout in set() sollten immer gesetzt werden, um hängende Verbindungen zu vermeiden.
  • Fehlerbehandlung: Prüfen Sie nach connect(), send() und recv() stets den Rückgabewert sowie $client->errCode und $client->errMsg.
  • Protokollerkennung: Für strukturierte Protokolle (z. B. HTTP, MQTT) empfiehlt sich die Konfiguration von open_length_check oder open_eof_check über set(), um vollständige Pakete zu empfangen.
  • Ressourcen: Nach Gebrauch immer close() aufrufen, um Dateideskriptoren freizugeben.
  • Alternative: Für reine HTTP-Anfragen ist Swoole\Coroutine\Http\Client komfortabler, da er das HTTP-Protokoll vollständig kapselt.