Asynchrone, Streaming-Klartext-TCP/IP- und sichere TLS-Socket-Server- und Client-Verbindungen für ReactPHP.
Entwicklungsversion: Dieser Zweig enthält den Code für die kommende v3-Version. Den Code der aktuellen stabilen v1-Version finden Sie im
1.x
Zweig.Die kommende Version 3 wird der Weg für die Zukunft dieses Pakets sein. Wir werden Version 1 jedoch weiterhin aktiv für diejenigen unterstützen, die noch nicht über die neueste Version verfügen. Weitere Einzelheiten finden Sie auch in der Installationsanleitung.
Die Socket-Bibliothek bietet wiederverwendbare Schnittstellen für einen Socket-Layer-Server und -Client basierend auf den EventLoop
und Stream
Komponenten. Mit seiner Serverkomponente können Sie Netzwerkserver erstellen, die eingehende Verbindungen von Netzwerkclients (z. B. einem HTTP-Server) akzeptieren. Mit seiner Client-Komponente können Sie Netzwerk-Clients erstellen, die ausgehende Verbindungen zu Netzwerkservern herstellen (z. B. einen HTTP- oder Datenbank-Client). Diese Bibliothek bietet für all dies asynchrone Streaming-Möglichkeiten, sodass Sie mehrere gleichzeitige Verbindungen ohne Blockierung verarbeiten können.
Inhaltsverzeichnis
Hier ist ein Server, der die Verbindung schließt, wenn Sie ihm etwas senden:
$ socket = new React Socket SocketServer ( ' 127.0.0.1:8080 ' );
$ socket -> on ( ' connection ' , function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( " Hello " . $ connection -> getRemoteAddress () . " ! n" );
$ connection -> write ( " Welcome to this amazing server! n" );
$ connection -> write ( " Here's a tip: don't say anything. n" );
$ connection -> on ( ' data ' , function ( $ data ) use ( $ connection ) {
$ connection -> close ();
});
});
Siehe auch die Beispiele.
Hier ist ein Client, der die Ausgabe des Servers ausgibt und dann versucht, ihm eine Zeichenfolge zu senden:
$ connector = new React Socket Connector ();
$ connector -> connect ( ' 127.0.0.1:8080 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> pipe ( new React Stream WritableResourceStream ( STDOUT ));
$ connection -> write ( " Hello World! n" );
}, function ( Exception $ e ) {
echo ' Error: ' . $ e -> getMessage () . PHP_EOL ;
});
Das ConnectionInterface
wird verwendet, um jede eingehende und ausgehende Verbindung darzustellen, beispielsweise eine normale TCP/IP-Verbindung.
Eine eingehende oder ausgehende Verbindung ist ein Duplex-Stream (sowohl lesbar als auch beschreibbar), der DuplexStreamInterface
von React implementiert. Es enthält zusätzliche Eigenschaften für die lokale und Remote-Adresse (Client-IP), zu der bzw. von der diese Verbindung hergestellt wurde.
Am häufigsten werden Instanzen, die dieses ConnectionInterface
implementieren, von allen Klassen ausgegeben, die das ServerInterface
implementieren, und von allen Klassen verwendet, die das ConnectorInterface
implementieren.
Da ConnectionInterface
das zugrunde liegende DuplexStreamInterface
implementiert, können Sie alle seine Ereignisse und Methoden wie gewohnt verwenden:
$ connection -> on ( ' data ' , function ( $ chunk ) {
echo $ chunk ;
});
$ connection -> on ( ' end ' , function () {
echo ' ended ' ;
});
$ connection -> on ( ' error ' , function ( Exception $ e ) {
echo ' error: ' . $ e -> getMessage ();
});
$ connection -> on ( ' close ' , function () {
echo ' closed ' ;
});
$ connection -> write ( $ data );
$ connection -> end ( $ data = null );
$ connection -> close ();
// …
Weitere Einzelheiten finden Sie im DuplexStreamInterface
.
Die Methode getRemoteAddress(): ?string
gibt die vollständige Remote-Adresse (URI) zurück, mit der diese Verbindung hergestellt wurde.
$ address = $ connection -> getRemoteAddress ();
echo ' Connection with ' . $ address . PHP_EOL ;
Wenn die Remote-Adresse zu diesem Zeitpunkt nicht ermittelt werden kann oder unbekannt ist (z. B. nachdem die Verbindung geschlossen wurde), wird möglicherweise stattdessen ein NULL
-Wert zurückgegeben.
Andernfalls wird die vollständige Adresse (URI) als Zeichenfolgenwert zurückgegeben, z. B. tcp://127.0.0.1:8080
, tcp://[::1]:80
, tls://127.0.0.1:443
, unix://example.sock
oder unix:///path/to/example.sock
. Beachten Sie, dass einzelne URI-Komponenten anwendungsspezifisch sind und vom zugrunde liegenden Transportprotokoll abhängen.
Wenn es sich um eine TCP/IP-basierte Verbindung handelt und Sie nur die Remote-IP möchten, können Sie etwa Folgendes verwenden:
$ address = $ connection -> getRemoteAddress ();
$ ip = trim ( parse_url ( $ address , PHP_URL_HOST ), ' [] ' );
echo ' Connection with ' . $ ip . PHP_EOL ;
Die Methode getLocalAddress(): ?string
gibt die vollständige lokale Adresse (URI) zurück, mit der diese Verbindung hergestellt wurde.
$ address = $ connection -> getLocalAddress ();
echo ' Connection with ' . $ address . PHP_EOL ;
Wenn die lokale Adresse zu diesem Zeitpunkt nicht ermittelt werden kann oder unbekannt ist (z. B. nachdem die Verbindung geschlossen wurde), wird möglicherweise stattdessen ein NULL
Wert zurückgegeben.
Andernfalls wird die vollständige Adresse (URI) als Zeichenfolgenwert zurückgegeben, z. B. tcp://127.0.0.1:8080
, tcp://[::1]:80
, tls://127.0.0.1:443
, unix://example.sock
oder unix:///path/to/example.sock
. Beachten Sie, dass einzelne URI-Komponenten anwendungsspezifisch sind und vom zugrunde liegenden Transportprotokoll abhängen.
Diese Methode ergänzt die Methode getRemoteAddress()
und sollte daher nicht verwechselt werden.
Wenn Ihre TcpServer
-Instanz auf mehreren Schnittstellen lauscht (z. B. über die Adresse 0.0.0.0
), können Sie mit dieser Methode herausfinden, welche Schnittstelle diese Verbindung tatsächlich akzeptiert hat (z. B. eine öffentliche oder lokale Schnittstelle).
Wenn Ihr System über mehrere Schnittstellen verfügt (z. B. eine WAN- und eine LAN-Schnittstelle), können Sie mit dieser Methode herausfinden, welche Schnittstelle tatsächlich für diese Verbindung verwendet wurde.
Das ServerInterface
ist für die Bereitstellung einer Schnittstelle zum Akzeptieren eingehender Streaming-Verbindungen verantwortlich, beispielsweise einer normalen TCP/IP-Verbindung.
Die meisten übergeordneten Komponenten (z. B. ein HTTP-Server) akzeptieren eine Instanz, die diese Schnittstelle implementiert, um eingehende Streaming-Verbindungen zu akzeptieren. Dies erfolgt normalerweise über die Abhängigkeitsinjektion, daher ist es ziemlich einfach, diese Implementierung tatsächlich gegen eine andere Implementierung dieser Schnittstelle auszutauschen. Das bedeutet, dass Sie einen Hinweis auf diese Schnittstelle anstelle einer konkreten Implementierung dieser Schnittstelle eingeben sollten.
Neben der Definition einiger Methoden implementiert diese Schnittstelle auch das EventEmitterInterface
, mit dem Sie auf bestimmte Ereignisse reagieren können.
Das connection
wird immer dann ausgegeben, wenn eine neue Verbindung hergestellt wurde, d. h. ein neuer Client eine Verbindung zu diesem Server-Socket herstellt:
$ socket -> on ( ' connection ' , function ( React Socket ConnectionInterface $ connection ) {
echo ' new connection ' . PHP_EOL ;
});
Weitere Informationen zum Umgang mit der eingehenden Verbindung finden Sie auch unter ConnectionInterface
.
Das error
wird immer dann ausgegeben, wenn beim Akzeptieren einer neuen Verbindung von einem Client ein Fehler auftritt.
$ socket -> on ( ' error ' , function ( Exception $ e ) {
echo ' error: ' . $ e -> getMessage () . PHP_EOL ;
});
Beachten Sie, dass es sich hierbei nicht um ein schwerwiegendes Fehlerereignis handelt, d. h. der Server wartet auch nach diesem Ereignis weiterhin auf neue Verbindungen.
Die Methode getAddress(): ?string
kann verwendet werden, um die vollständige Adresse (URI) zurückzugeben, die dieser Server derzeit überwacht.
$ address = $ socket -> getAddress ();
echo ' Server listening on ' . $ address . PHP_EOL ;
Wenn die Adresse zu diesem Zeitpunkt nicht ermittelt werden kann oder unbekannt ist (z. B. nachdem der Socket geschlossen wurde), wird möglicherweise stattdessen ein NULL
-Wert zurückgegeben.
Andernfalls wird die vollständige Adresse (URI) als Zeichenfolgenwert zurückgegeben, z. B. tcp://127.0.0.1:8080
, tcp://[::1]:80
, tls://127.0.0.1:443
unix://example.sock
oder unix:///path/to/example.sock
. Beachten Sie, dass einzelne URI-Komponenten anwendungsspezifisch sind und vom zugrunde liegenden Transportprotokoll abhängen.
Wenn es sich um einen TCP/IP-basierten Server handelt und Sie nur den lokalen Port benötigen, können Sie etwa Folgendes verwenden:
$ address = $ socket -> getAddress ();
$ port = parse_url ( $ address , PHP_URL_PORT );
echo ' Server listening on port ' . $ port . PHP_EOL ;
Mit der Methode pause(): void
kann die Annahme neuer eingehender Verbindungen angehalten werden.
Entfernt die Socket-Ressource aus der EventLoop und akzeptiert somit keine neuen Verbindungen mehr. Beachten Sie, dass der Listening-Socket aktiv bleibt und nicht geschlossen wird.
Das bedeutet, dass neue eingehende Verbindungen im Betriebssystem-Backlog ausstehend bleiben, bis der konfigurierbare Backlog gefüllt ist. Sobald der Rückstand aufgefüllt ist, lehnt das Betriebssystem möglicherweise weitere eingehende Verbindungen ab, bis der Rückstand wieder geleert wird, indem es wieder neue Verbindungen akzeptiert.
Sobald der Server angehalten ist, SOLLTEN keine weiteren connection
ausgegeben werden.
$ socket -> pause ();
$ socket -> on ( ' connection ' , assertShouldNeverCalled ());
Diese Methode dient nur der Empfehlung, wird jedoch im Allgemeinen nicht empfohlen. Der Server sendet möglicherweise weiterhin connection
aus.
Sofern nicht anders angegeben, sollte ein erfolgreich geöffneter Server NICHT im angehaltenen Zustand starten.
Sie können mit der Verarbeitung von Ereignissen fortfahren, indem Sie resume()
erneut aufrufen.
Beachten Sie, dass beide Methoden beliebig oft aufgerufen werden können, insbesondere der mehrmalige Aufruf von pause()
SOLLTE KEINE Auswirkung haben. Ebenso ist der Aufruf nach close()
ein NO-OP.
Die Methode resume(): void
kann verwendet werden, um die Annahme neuer eingehender Verbindungen fortzusetzen.
Hängen Sie die Socket-Ressource nach einer vorherigen pause()
erneut an den EventLoop an.
$ socket -> pause ();
Loop:: addTimer ( 1.0 , function () use ( $ socket ) {
$ socket -> resume ();
});
Beachten Sie, dass beide Methoden beliebig oft aufgerufen werden können, insbesondere der Aufruf von resume()
ohne vorherige pause()
sollte KEINE Wirkung haben. Ebenso ist der Aufruf nach close()
ein NO-OP.
Mit der Methode close(): void
kann dieser Listening-Socket geschlossen werden.
Dadurch wird die Überwachung auf neue eingehende Verbindungen an diesem Socket beendet.
echo ' Shutting down server socket ' . PHP_EOL ;
$ socket -> close ();
Der mehrmalige Aufruf dieser Methode für dieselbe Instanz ist ein NO-OP.
Die SocketServer
-Klasse ist die Hauptklasse in diesem Paket, die das ServerInterface
implementiert und Ihnen die Annahme eingehender Streaming-Verbindungen ermöglicht, z. B. Klartext-TCP/IP oder sichere TLS-Verbindungsströme.
Um Klartext-TCP/IP-Verbindungen zu akzeptieren, können Sie einfach eine Kombination aus Host und Port wie folgt übergeben:
$ socket = new React Socket SocketServer ( ' 127.0.0.1:8080 ' );
Das Abhören der Localhost-Adresse 127.0.0.1
bedeutet, dass sie von außerhalb dieses Systems nicht erreichbar ist. Um den Host zu ändern, auf dem der Socket lauscht, können Sie eine IP-Adresse einer Schnittstelle angeben oder die spezielle Adresse 0.0.0.0
verwenden, um alle Schnittstellen abzuhören:
$ socket = new React Socket SocketServer ( ' 0.0.0.0:8080 ' );
Wenn Sie eine IPv6-Adresse abhören möchten, MÜSSEN Sie den Host in eckige Klammern setzen:
$ socket = new React Socket SocketServer ( ' [::1]:8080 ' );
Um eine zufällige Portzuweisung zu verwenden, können Sie den Port 0
verwenden:
$ socket = new React Socket SocketServer ( ' 127.0.0.1:0 ' );
$ address = $ socket -> getAddress ();
Um einen Unix-Domain-Socket-Pfad (UDS) abzuhören, MÜSSEN Sie dem URI das Schema unix://
voranstellen:
$ socket = new React Socket SocketServer ( ' unix:///tmp/server.sock ' );
Um eine vorhandene Dateideskriptornummer (FD) abzuhören, MÜSSEN Sie dem URI php://fd/
wie folgt voranstellen:
$ socket = new React Socket SocketServer ( ' php://fd/3 ' );
Wenn der angegebene URI ungültig ist, keinen Port oder ein anderes Schema enthält oder einen Hostnamen enthält, wird eine InvalidArgumentException
ausgelöst:
// throws InvalidArgumentException due to missing port
$ socket = new React Socket SocketServer ( ' 127.0.0.1 ' );
Wenn der angegebene URI gültig zu sein scheint, das Abhören jedoch fehlschlägt (z. B. wenn ein Port bereits verwendet wird oder ein Port unter 1024 möglicherweise Root-Zugriff erfordert usw.), wird eine RuntimeException
ausgelöst:
$ first = new React Socket SocketServer ( ' 127.0.0.1:8080 ' );
// throws RuntimeException because port is already in use
$ second = new React Socket SocketServer ( ' 127.0.0.1:8080 ' );
Beachten Sie, dass diese Fehlerbedingungen je nach System und/oder Konfiguration variieren können. Weitere Einzelheiten zum tatsächlichen Fehlerzustand finden Sie in der Ausnahmemeldung und im Code.
Optional können Sie TCP-Socket-Kontextoptionen für die zugrunde liegende Stream-Socket-Ressource wie folgt angeben:
$ socket = new React Socket SocketServer ( ' [::1]:8080 ' , [
' tcp ' => [
' backlog ' => 200 ,
' so_reuseport ' => true ,
' ipv6_v6only ' => true
]
]);
Beachten Sie, dass die verfügbaren Socket-Kontextoptionen, ihre Standardeinstellungen und die Auswirkungen ihrer Änderung je nach System und/oder PHP-Version variieren können. Die Übergabe unbekannter Kontextoptionen hat keine Auswirkung. Die
backlog
-Kontextoption ist standardmäßig auf511
eingestellt, sofern nicht ausdrücklich angegeben.
Sie können einen sicheren TLS-Server (früher bekannt als SSL) starten, indem Sie einfach das URI-Schema tls://
voranstellen. Intern wartet es auf Klartext-TCP/IP-Verbindungen und führt dann für jede Verbindung einen TLS-Handshake durch. Es erfordert daher gültige TLS-Kontextoptionen, die in ihrer einfachsten Form etwa so aussehen können, wenn Sie eine PEM-codierte Zertifikatsdatei verwenden:
$ socket = new React Socket SocketServer ( ' tls://127.0.0.1:8080 ' , [
' tls ' => [
' local_cert ' => ' server.pem '
]
]);
Beachten Sie, dass die Zertifikatsdatei nicht bei der Instanziierung geladen wird, sondern wenn eine eingehende Verbindung ihren TLS-Kontext initialisiert. Dies bedeutet, dass ungültige Zertifikatdateipfade oder -inhalte erst zu einem späteren Zeitpunkt ein
error
verursachen.
Wenn Ihr privater Schlüssel mit einer Passphrase verschlüsselt ist, müssen Sie diese wie folgt angeben:
$ socket = new React Socket SocketServer ( ' tls://127.0.0.1:8000 ' , [
' tls ' => [
' local_cert ' => ' server.pem ' ,
' passphrase ' => ' secret '
]
]);
Standardmäßig unterstützt dieser Server TLSv1.0+ und schließt die Unterstützung für Legacy-SSLv2/SSLv3 aus. Sie können auch explizit die TLS-Version auswählen, die Sie mit der Gegenseite aushandeln möchten:
$ socket = new React Socket SocketServer ( ' tls://127.0.0.1:8000 ' , [
' tls ' => [
' local_cert ' => ' server.pem ' ,
' crypto_method ' => STREAM_CRYPTO_METHOD_TLSv1_2_SERVER
]
]);
Beachten Sie, dass die verfügbaren TLS-Kontextoptionen, ihre Standardeinstellungen und die Auswirkungen ihrer Änderung je nach System und/oder PHP-Version variieren können. Mit dem äußeren Kontextarray können Sie gleichzeitig auch
tcp
Kontextoptionen (und möglicherweise weitere) verwenden. Die Übergabe unbekannter Kontextoptionen hat keine Auswirkung. Wenn Sie dastls://
-Schema nicht verwenden, hat die Übergabetls
Kontextoptionen keine Auswirkung.
Immer wenn ein Client eine Verbindung herstellt, gibt er ein connection
mit einer Verbindungsinstanz aus, ConnectionInterface
implementiert:
$ socket -> on ( ' connection ' , function ( React Socket ConnectionInterface $ connection ) {
echo ' Plaintext connection from ' . $ connection -> getRemoteAddress () . PHP_EOL ;
$ connection -> write ( ' hello there! ' . PHP_EOL );
…
});
Weitere Informationen finden Sie auch im ServerInterface
.
Diese Klasse akzeptiert einen optionalen LoopInterface|null $loop
Parameter, der verwendet werden kann, um die Ereignisschleifeninstanz zu übergeben, die für dieses Objekt verwendet werden soll. Sie können hier einen null
verwenden, um die Standardschleife zu verwenden. Dieser Wert SOLLTE NICHT angegeben werden, es sei denn, Sie sind sicher, dass Sie eine bestimmte Ereignisschleifeninstanz explizit verwenden möchten.
Beachten Sie, dass die
SocketServer
-Klasse eine konkrete Implementierung für TCP/IP-Sockets ist. Wenn Sie in Ihrer Protokollimplementierung auf höherer Ebene Typehints verwenden möchten, SOLLTEN Sie stattdessen das generischeServerInterface
verwenden.
Die TcpServer
-Klasse implementiert das ServerInterface
und ist für die Annahme von Klartext-TCP/IP-Verbindungen verantwortlich.
$ server = new React Socket TcpServer ( 8080 );
Wie oben kann der Parameter $uri
nur aus einem Port bestehen. In diesem Fall überwacht der Server standardmäßig die Localhost-Adresse 127.0.0.1
, was bedeutet, dass er von außerhalb dieses Systems nicht erreichbar ist.
Um eine zufällige Portzuweisung zu verwenden, können Sie den Port 0
verwenden:
$ server = new React Socket TcpServer ( 0 );
$ address = $ server -> getAddress ();
Um den Host zu ändern, auf dem der Socket lauscht, können Sie über den ersten Parameter, der dem Konstruktor bereitgestellt wird, eine IP-Adresse angeben, optional vorangestellt durch das Schema tcp://
:
$ server = new React Socket TcpServer ( ' 192.168.0.1:8080 ' );
Wenn Sie eine IPv6-Adresse abhören möchten, MÜSSEN Sie den Host in eckige Klammern setzen:
$ server = new React Socket TcpServer ( ' [::1]:8080 ' );
Wenn der angegebene URI ungültig ist, keinen Port oder ein anderes Schema enthält oder einen Hostnamen enthält, wird eine InvalidArgumentException
ausgelöst:
// throws InvalidArgumentException due to missing port
$ server = new React Socket TcpServer ( ' 127.0.0.1 ' );
Wenn der angegebene URI gültig zu sein scheint, das Abhören jedoch fehlschlägt (z. B. wenn ein Port bereits verwendet wird oder ein Port unter 1024 möglicherweise Root-Zugriff erfordert usw.), wird eine RuntimeException
ausgelöst:
$ first = new React Socket TcpServer ( 8080 );
// throws RuntimeException because port is already in use
$ second = new React Socket TcpServer ( 8080 );
Beachten Sie, dass diese Fehlerbedingungen je nach System und/oder Konfiguration variieren können. Weitere Einzelheiten zum tatsächlichen Fehlerzustand finden Sie in der Ausnahmemeldung und im Code.
Diese Klasse akzeptiert einen optionalen LoopInterface|null $loop
Parameter, der verwendet werden kann, um die Ereignisschleifeninstanz zu übergeben, die für dieses Objekt verwendet werden soll. Sie können hier einen null
verwenden, um die Standardschleife zu verwenden. Dieser Wert SOLLTE NICHT angegeben werden, es sei denn, Sie sind sicher, dass Sie eine bestimmte Ereignisschleifeninstanz explizit verwenden möchten.
Optional können Sie Socket-Kontextoptionen für die zugrunde liegende Stream-Socket-Ressource wie folgt angeben:
$ server = new React Socket TcpServer ( ' [::1]:8080 ' , null , [
' backlog ' => 200 ,
' so_reuseport ' => true ,
' ipv6_v6only ' => true
]);
Beachten Sie, dass die verfügbaren Socket-Kontextoptionen, ihre Standardeinstellungen und die Auswirkungen ihrer Änderung je nach System und/oder PHP-Version variieren können. Die Übergabe unbekannter Kontextoptionen hat keine Auswirkung. Die
backlog
-Kontextoption ist standardmäßig auf511
eingestellt, sofern nicht ausdrücklich angegeben.
Immer wenn ein Client eine Verbindung herstellt, gibt er ein connection
mit einer Verbindungsinstanz aus, ConnectionInterface
implementiert:
$ server -> on ( ' connection ' , function ( React Socket ConnectionInterface $ connection ) {
echo ' Plaintext connection from ' . $ connection -> getRemoteAddress () . PHP_EOL ;
$ connection -> write ( ' hello there! ' . PHP_EOL );
…
});
Weitere Informationen finden Sie auch im ServerInterface
.
Die SecureServer
-Klasse implementiert das ServerInterface
und ist für die Bereitstellung eines sicheren TLS-Servers (früher bekannt als SSL) verantwortlich.
Dazu wird eine TcpServer
-Instanz umschlossen, die auf Klartext-TCP/IP-Verbindungen wartet und dann für jede Verbindung einen TLS-Handshake durchführt. Es erfordert daher gültige TLS-Kontextoptionen, die in ihrer einfachsten Form etwa so aussehen können, wenn Sie eine PEM-codierte Zertifikatsdatei verwenden:
$ server = new React Socket TcpServer ( 8000 );
$ server = new React Socket SecureServer ( $ server , null , [
' local_cert ' => ' server.pem '
]);
Beachten Sie, dass die Zertifikatsdatei nicht bei der Instanziierung geladen wird, sondern wenn eine eingehende Verbindung ihren TLS-Kontext initialisiert. Dies bedeutet, dass ungültige Zertifikatdateipfade oder -inhalte erst zu einem späteren Zeitpunkt ein
error
verursachen.
Wenn Ihr privater Schlüssel mit einer Passphrase verschlüsselt ist, müssen Sie diese wie folgt angeben:
$ server = new React Socket TcpServer ( 8000 );
$ server = new React Socket SecureServer ( $ server , null , [
' local_cert ' => ' server.pem ' ,
' passphrase ' => ' secret '
]);
Standardmäßig unterstützt dieser Server TLSv1.0+ und schließt die Unterstützung für Legacy-SSLv2/SSLv3 aus. Sie können auch explizit die TLS-Version auswählen, die Sie mit der Gegenseite aushandeln möchten:
$ server = new React Socket TcpServer ( 8000 );
$ server = new React Socket SecureServer ( $ server , null , [
' local_cert ' => ' server.pem ' ,
' crypto_method ' => STREAM_CRYPTO_METHOD_TLSv1_2_SERVER
]);
Beachten Sie, dass die verfügbaren TLS-Kontextoptionen, ihre Standardeinstellungen und die Auswirkungen ihrer Änderung je nach System und/oder PHP-Version variieren können. Die Übergabe unbekannter Kontextoptionen hat keine Auswirkung.
Immer wenn ein Client den TLS-Handshake abschließt, gibt er ein connection
mit einer Verbindungsinstanz aus, ConnectionInterface
implementiert:
$ server -> on ( ' connection ' , function ( React Socket ConnectionInterface $ connection ) {
echo ' Secure connection from ' . $ connection -> getRemoteAddress () . PHP_EOL ;
$ connection -> write ( ' hello there! ' . PHP_EOL );
…
});
Wenn ein Client keinen erfolgreichen TLS-Handshake durchführt, gibt er ein error
aus und schließt dann die zugrunde liegende TCP/IP-Verbindung:
$ server -> on ( ' error ' , function ( Exception $ e ) {
echo ' Error ' . $ e -> getMessage () . PHP_EOL ;
});
Weitere Informationen finden Sie auch im ServerInterface
.
Beachten Sie, dass die SecureServer
-Klasse eine konkrete Implementierung für TLS-Sockets ist. Wenn Sie in Ihrer Protokollimplementierung auf höherer Ebene Typehints verwenden möchten, SOLLTEN Sie stattdessen das generische ServerInterface
verwenden.
Diese Klasse akzeptiert einen optionalen LoopInterface|null $loop
Parameter, der verwendet werden kann, um die Ereignisschleifeninstanz zu übergeben, die für dieses Objekt verwendet werden soll. Sie können hier einen null
verwenden, um die Standardschleife zu verwenden. Dieser Wert SOLLTE NICHT angegeben werden, es sei denn, Sie sind sicher, dass Sie eine bestimmte Ereignisschleifeninstanz explizit verwenden möchten.
Erweiterte Verwendung: Obwohl Sie jedes
ServerInterface
als ersten Parameter zulassen, SOLLTEN Sie eineTcpServer
-Instanz als ersten Parameter übergeben, es sei denn, Sie wissen, was Sie tun. Intern muss derSecureServer
die erforderlichen TLS-Kontextoptionen für die zugrunde liegenden Stream-Ressourcen festlegen. Diese Ressourcen werden über keine der in diesem Paket definierten Schnittstellen verfügbar gemacht, sondern nur über die interneConnection
Klasse. DieTcpServer
-Klasse gibt garantiert Verbindungen aus, die dasConnectionInterface
implementieren, und verwendet die interneConnection
Klasse, um diese zugrunde liegenden Ressourcen verfügbar zu machen. Wenn Sie ein benutzerdefiniertesServerInterface
verwenden und dessenconnection
diese Anforderung nicht erfüllt, gibt derSecureServer
einerror
aus und schließt dann die zugrunde liegende Verbindung.
Die UnixServer
-Klasse implementiert das ServerInterface
und ist für die Annahme von Verbindungen auf Unix-Domänen-Sockets (UDS) verantwortlich.
$ server = new React Socket UnixServer ( ' /tmp/server.sock ' );
Wie oben kann der Parameter $uri
nur aus einem Socket-Pfad oder einem Socket-Pfad mit dem Präfix unix://
bestehen.
Wenn der angegebene URI gültig zu sein scheint, das Abhören jedoch fehlschlägt (z. B. wenn der Socket bereits verwendet wird oder auf die Datei nicht zugegriffen werden kann usw.), wird eine RuntimeException
ausgelöst:
$ first = new React Socket UnixServer ( ' /tmp/same.sock ' );
// throws RuntimeException because socket is already in use
$ second = new React Socket UnixServer ( ' /tmp/same.sock ' );
Beachten Sie, dass diese Fehlerbedingungen je nach System und/oder Konfiguration variieren können. Insbesondere meldet Zend PHP nur dann „Unbekannter Fehler“, wenn der UDS-Pfad bereits existiert und nicht gebunden werden kann. Möglicherweise möchten Sie
is_file()
auf dem angegebenen UDS-Pfad überprüfen, um in diesem Fall eine benutzerfreundlichere Fehlermeldung zu melden. Weitere Einzelheiten zum tatsächlichen Fehlerzustand finden Sie in der Ausnahmemeldung und im Code.
Diese Klasse akzeptiert einen optionalen LoopInterface|null $loop
Parameter, der verwendet werden kann, um die Ereignisschleifeninstanz zu übergeben, die für dieses Objekt verwendet werden soll. Sie können hier einen null
verwenden, um die Standardschleife zu verwenden. Dieser Wert SOLLTE NICHT angegeben werden, es sei denn, Sie sind sicher, dass Sie eine bestimmte Ereignisschleifeninstanz explizit verwenden möchten.
Immer wenn ein Client eine Verbindung herstellt, gibt er ein connection
mit einer Verbindungsinstanz aus, ConnectionInterface
implementiert:
$ server -> on ( ' connection ' , function ( React Socket ConnectionInterface $ connection ) {
echo ' New connection ' . PHP_EOL ;
$ connection -> write ( ' hello there! ' . PHP_EOL );
…
});
Weitere Informationen finden Sie auch im ServerInterface
.
Der LimitingServer
Dekorator umschließt ein bestimmtes ServerInterface
und ist dafür verantwortlich, offene Verbindungen zu dieser Serverinstanz einzuschränken und zu verfolgen.
Immer wenn der zugrunde liegende Server ein connection
ausgibt, überprüft er seine Grenzen und dann entweder
connection
weiterleitenerror
weiter.Immer wenn eine Verbindung geschlossen wird, wird diese Verbindung aus der Liste der offenen Verbindungen entfernt.
$ server = new React Socket LimitingServer ( $ server , 100 );
$ server -> on ( ' connection ' , function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' hello there! ' . PHP_EOL );
…
});
Weitere Einzelheiten finden Sie auch im zweiten Beispiel.
Sie müssen eine maximale Anzahl offener Verbindungen übergeben, um sicherzustellen, dass der Server Verbindungen automatisch ablehnt (schließt), sobald diese Grenze überschritten wird. In diesem Fall wird ein error
ausgegeben, um darüber zu informieren, und es wird kein connection
ausgegeben.
$ server = new React Socket LimitingServer ( $ server , 100 );
$ server -> on ( ' connection ' , function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' hello there! ' . PHP_EOL );
…
});
Sie KÖNNEN ein null
Limit übergeben, um die Anzahl der offenen Verbindungen unbegrenzt zu begrenzen und weiterhin neue Verbindungen zu akzeptieren, bis Ihnen die Betriebssystemressourcen ausgehen (z. B. offene Dateihandles). Dies kann nützlich sein, wenn Sie sich nicht um die Anwendung eines Limits kümmern möchten, aber dennoch die Methode getConnections()
verwenden möchten.
Sie können den Server optional so konfigurieren, dass er die Annahme neuer Verbindungen pausiert, sobald das Verbindungslimit erreicht ist. In diesem Fall wird der zugrunde liegende Server angehalten und keine neuen Verbindungen mehr verarbeitet, sodass auch keine übermäßigen Verbindungen mehr geschlossen werden. Das zugrunde liegende Betriebssystem ist dafür verantwortlich, einen Rückstand an ausstehenden Verbindungen aufrechtzuerhalten, bis sein Limit erreicht ist. Ab diesem Zeitpunkt beginnt es, weitere Verbindungen abzulehnen. Sobald der Server das Verbindungslimit unterschreitet, verbraucht er weiterhin Verbindungen aus dem Backlog und verarbeitet alle ausstehenden Daten bei jeder Verbindung. Dieser Modus kann für einige Protokolle nützlich sein, die darauf ausgelegt sind, auf eine Antwortnachricht zu warten (z. B. HTTP), ist jedoch möglicherweise weniger nützlich für andere Protokolle, die sofortige Antworten erfordern (z. B. eine „Willkommens“-Nachricht in einem interaktiven Chat).
$ server = new React Socket LimitingServer ( $ server , 100 , true );
$ server -> on ( ' connection ' , function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' hello there! ' . PHP_EOL );
…
});
Mit der Methode getConnections(): ConnectionInterface[]
kann ein Array mit allen aktuell aktiven Verbindungen zurückgegeben werden.
foreach ( $ server -> getConnection () as $ connection ) {
$ connection -> write ( ' Hi! ' );
}
Das ConnectorInterface
ist für die Bereitstellung einer Schnittstelle zum Aufbau von Streaming-Verbindungen verantwortlich, beispielsweise einer normalen TCP/IP-Verbindung.
Dies ist die in diesem Paket definierte Hauptschnittstelle und wird im gesamten riesigen Ökosystem von React verwendet.
Die meisten übergeordneten Komponenten (z. B. HTTP-, Datenbank- oder andere Netzwerkdienst-Clients) akzeptieren eine Instanz, die diese Schnittstelle implementiert, um ihre TCP/IP-Verbindung zum zugrunde liegenden Netzwerkdienst herzustellen. Dies erfolgt normalerweise über die Abhängigkeitsinjektion, daher ist es ziemlich einfach, diese Implementierung tatsächlich gegen eine andere Implementierung dieser Schnittstelle auszutauschen.
Die Schnittstelle bietet nur eine einzige Methode:
Die Methode connect(string $uri): PromiseInterface<ConnectionInterface>
kann verwendet werden, um eine Streaming-Verbindung zur angegebenen Remote-Adresse herzustellen.
Es gibt ein Versprechen zurück, das entweder bei Erfolg mit einem Stream erfüllt wird, ConnectionInterface
implementiert, oder es mit einer Exception
ablehnt, wenn die Verbindung nicht erfolgreich ist:
$ connector -> connect ( ' google.com:443 ' )-> then (
function ( React Socket ConnectionInterface $ connection ) {
// connection successfully established
},
function ( Exception $ error ) {
// failed to connect due to $error
}
);
Weitere Informationen finden Sie auch unter ConnectionInterface
.
Das zurückgegebene Versprechen MUSS so umgesetzt werden, dass es storniert werden kann, wenn es noch aussteht. Das Abbrechen eines ausstehenden Versprechens MUSS seinen Wert mit einer Exception
ablehnen. Es SOLLTE gegebenenfalls alle zugrunde liegenden Ressourcen und Referenzen bereinigen:
$ promise = $ connector -> connect ( $ uri );
$ promise -> cancel ();
Die Connector
-Klasse ist die Hauptklasse in diesem Paket, die ConnectorInterface
implementiert und Ihnen das Erstellen von Streaming-Verbindungen ermöglicht.
Mit diesem Connector können Sie jede Art von Streaming-Verbindungen erstellen, z. B. Klartext-TCP/IP, sicheres TLS oder lokale Unix-Verbindungsstreams.
Es bindet an die Hauptereignisschleife und kann wie folgt verwendet werden:
$ connector = new React Socket Connector ();
$ connector -> connect ( $ uri )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
}, function ( Exception $ e ) {
echo ' Error: ' . $ e -> getMessage () . PHP_EOL ;
});
Um eine Klartext-TCP/IP-Verbindung zu erstellen, können Sie einfach eine Kombination aus Host und Port wie folgt übergeben:
$ connector -> connect ( ' www.google.com:80 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
Wenn Sie im Ziel-URI kein URI-Schema angeben, wird
tcp://
als Standard angenommen und eine Klartext-TCP/IP-Verbindung hergestellt. Beachten Sie, dass TCP/IP-Verbindungen wie oben einen Host- und Port-Teil im Ziel-URI erfordern; alle anderen URI-Komponenten sind optional.
Um eine sichere TLS-Verbindung herzustellen, können Sie das URI-Schema tls://
wie folgt verwenden:
$ connector -> connect ( ' tls://www.google.com:443 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
Um eine lokale Unix-Domänen-Socket-Verbindung zu erstellen, können Sie das URI-Schema unix://
wie folgt verwenden:
$ connector -> connect ( ' unix:///tmp/demo.sock ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
Die
getRemoteAddress()
Methode gibt den Ziel-Unix-Domain-Socket-Pfad (UDS) zurück, wie er an dieconnect()
Methode übergeben wurde, einschließlich desunix://
-Schemas, zum Beispielunix:///tmp/demo.sock
. Die MethodegetLocalAddress()
wird höchstwahrscheinlich einennull
zurückgeben, da dieser Wert hier nicht auf UDS-Verbindungen anwendbar ist.
Unter der Haube ist der Connector
als übergeordnete Fassade für die in diesem Paket implementierten Connectors auf niedrigerer Ebene implementiert. Dies bedeutet, dass auch alle Funktionen und Implementierungsdetails gemeinsam genutzt werden. Wenn Sie in Ihrer Protokollimplementierung auf höherer Ebene Typehints verwenden möchten, SOLLTEN Sie stattdessen das generische ConnectorInterface
verwenden.
Ab v1.4.0
verwendet die Connector
Klasse standardmäßig den Happy-Eyeballs-Algorithmus, um automatisch eine Verbindung über IPv4 oder IPv6 herzustellen, wenn ein Hostname angegeben wird. Dadurch wird automatisch versucht, gleichzeitig eine Verbindung über IPv4 und IPv6 herzustellen (wobei IPv6 bevorzugt wird), wodurch die üblichen Probleme vermieden werden, mit denen Benutzer mit unvollständigen IPv6-Verbindungen oder -Setups konfrontiert sind. Wenn Sie zum alten Verhalten zurückkehren möchten, nur eine IPv4-Suche durchzuführen und nur eine einzelne IPv4-Verbindung herzustellen, können Sie den Connector
wie folgt einrichten:
$ connector = new React Socket Connector ([
' happy_eyeballs ' => false
]);
Ebenso können Sie das Standard-DNS-Verhalten wie folgt beeinflussen. Die Connector
Klasse versucht, die DNS-Einstellungen Ihres Systems zu erkennen (und verwendet den öffentlichen DNS-Server 8.8.8.8
von Google als Fallback, wenn Ihre Systemeinstellungen nicht ermittelt werden können), um alle öffentlichen Hostnamen standardmäßig in zugrunde liegende IP-Adressen aufzulösen. Wenn Sie explizit einen benutzerdefinierten DNS-Server verwenden möchten (z. B. ein lokales DNS-Relay oder einen unternehmensweiten DNS-Server), können Sie den Connector
wie folgt einrichten:
$ connector = new React Socket Connector ([
' dns ' => ' 127.0.1.1 '
]);
$ connector -> connect ( ' localhost:80 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
Wenn Sie überhaupt keinen DNS-Resolver verwenden und nur eine Verbindung zu IP-Adressen herstellen möchten, können Sie Ihren Connector
auch wie folgt einrichten:
$ connector = new React Socket Connector ([
' dns ' => false
]);
$ connector -> connect ( ' 127.0.0.1:80 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
Erweitert: Wenn Sie eine benutzerdefinierte DNS ReactDnsResolverResolverInterface
Instanz benötigen, können Sie Ihren Connector
auch wie folgt einrichten:
$ dnsResolverFactory = new React Dns Resolver Factory ();
$ resolver = $ dnsResolverFactory -> createCached ( ' 127.0.1.1 ' );
$ connector = new React Socket Connector ([
' dns ' => $ resolver
]);
$ connector -> connect ( ' localhost:80 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
Standardmäßig verwenden die URI-Schemata tcp://
und tls://
einen Timeout-Wert, der Ihre default_socket_timeout
INI-Einstellung berücksichtigt (die standardmäßig 60 Sekunden beträgt). Wenn Sie einen benutzerdefinierten Timeout-Wert wünschen, können Sie diesen einfach wie folgt übergeben:
$ connector = new React Socket Connector ([
' timeout ' => 10.0
]);
Wenn Sie überhaupt kein Timeout anwenden und dies dem Betriebssystem überlassen möchten, können Sie ein boolesches Flag wie dieses übergeben:
$ connector = new React Socket Connector ([
' timeout ' => false
]);
Standardmäßig unterstützt der Connector
die URI-Schemata tcp://
, tls://
und unix://
. Wenn Sie eines davon explizit verbieten möchten, können Sie einfach boolesche Flags wie diese übergeben:
// only allow secure TLS connections
$ connector = new React Socket Connector ([
' tcp ' => false ,
' tls ' => true ,
' unix ' => false ,
));
$ connector -> connect ( ' tls://google.com:443 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
tcp://
und tls://
akzeptieren auch zusätzliche Kontextoptionen, die an die zugrunde liegenden Connectors übergeben werden. Wenn Sie zusätzliche Kontextoptionen explizit übergeben möchten, können Sie einfach Arrays von Kontextoptionen wie folgt übergeben:
// allow insecure TLS connections
$ connector = new React Socket Connector ([
' tcp ' => [
' bindto ' => ' 192.168.0.1:0 '
],
' tls ' => [
' verify_peer ' => false ,
' verify_peer_name ' => false
],
]);
$ connector -> connect ( ' tls://localhost:443 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
Standardmäßig unterstützt dieser Connector TLSv1.0+ und schließt die Unterstützung für Legacy-SSLv2/SSLv3 aus. Sie können auch explizit die TLS-Version auswählen, die Sie mit der Gegenseite aushandeln möchten:
$ connector = new React Socket Connector ([
' tls ' => [
' crypto_method ' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
]
]);
Weitere Einzelheiten zu Kontextoptionen finden Sie in der PHP-Dokumentation zu Socket-Kontextoptionen und SSL-Kontextoptionen.
Erweitert: Standardmäßig unterstützt der Connector
die URI-Schemata tcp://
, tls://
und unix://
. Hierzu richtet es automatisch die erforderlichen Connector-Klassen ein. Wenn Sie für einen dieser Konnektoren explizit benutzerdefinierte Konnektoren übergeben möchten, können Sie einfach eine Instanz übergeben, die ConnectorInterface
wie folgt implementiert:
$ dnsResolverFactory = new React Dns Resolver Factory ();
$ resolver = $ dnsResolverFactory -> createCached ( ' 127.0.1.1 ' );
$ tcp = new React Socket HappyEyeBallsConnector ( null , new React Socket TcpConnector (), $ resolver );
$ tls = new React Socket SecureConnector ( $ tcp );
$ unix = new React Socket UnixConnector ();
$ connector = new React Socket Connector ([
' tcp ' => $ tcp ,
' tls ' => $ tls ,
' unix ' => $ unix ,
' dns ' => false ,
' timeout ' => false ,
]);
$ connector -> connect ( ' google.com:80 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
Intern wird der
tcp://
Connector immer vom DNS-Resolver umschlossen, es sei denn, Sie deaktivieren DNS wie im obigen Beispiel. In diesem Fall erhält dertcp://
-Connector den tatsächlichen Hostnamen und nicht nur die aufgelöste IP-Adresse und ist somit für die Durchführung der Suche verantwortlich. Intern umhüllt der automatisch erstelltetls://
-Connector immer den zugrunde liegendentcp://
-Connector, um die zugrunde liegende Klartext-TCP/IP-Verbindung herzustellen, bevor der sichere TLS-Modus aktiviert wird. Wenn Sie einen benutzerdefinierten zugrunde liegendentcp://
-Connector nur für sichere TLS-Verbindungen verwenden möchten, können Sie stattdessen explizit einentls://
-Connector wie oben übergeben. Intern werden die Connectorstcp://
undtls://
immer vonTimeoutConnector
umschlossen, es sei denn, Sie deaktivieren Timeouts wie im obigen Beispiel.
Diese Klasse akzeptiert einen optionalen LoopInterface|null $loop
Parameter, der verwendet werden kann, um die Ereignisschleifeninstanz zu übergeben, die für dieses Objekt verwendet werden soll. Sie können hier einen null
verwenden, um die Standardschleife zu verwenden. Dieser Wert SOLLTE NICHT angegeben werden, es sei denn, Sie sind sicher, dass Sie eine bestimmte Ereignisschleifeninstanz explizit verwenden möchten.
Die TcpConnector
-Klasse implementiert das ConnectorInterface
und ermöglicht Ihnen das Erstellen von Klartext-TCP/IP-Verbindungen zu jeder IP-Port-Kombination:
$ tcpConnector = new React Socket TcpConnector ();
$ tcpConnector -> connect ( ' 127.0.0.1:80 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
Siehe auch die Beispiele.
Ausstehende Verbindungsversuche können abgebrochen werden, indem das ausstehende Versprechen wie folgt aufgehoben wird:
$ promise = $ tcpConnector -> connect ( ' 127.0.0.1:80 ' );
$ promise -> cancel ();
Durch den Aufruf von cancel()
für ein ausstehendes Versprechen wird die zugrunde liegende Socket-Ressource geschlossen, wodurch die ausstehende TCP/IP-Verbindung abgebrochen und das resultierende Versprechen abgelehnt wird.
Diese Klasse akzeptiert einen optionalen LoopInterface|null $loop
Parameter, der verwendet werden kann, um die Ereignisschleifeninstanz zu übergeben, die für dieses Objekt verwendet werden soll. Sie können hier einen null
verwenden, um die Standardschleife zu verwenden. Dieser Wert SOLLTE NICHT angegeben werden, es sei denn, Sie sind sicher, dass Sie eine bestimmte Ereignisschleifeninstanz explizit verwenden möchten.
Sie können optional zusätzliche Socket-Kontextoptionen wie folgt an den Konstruktor übergeben:
$ tcpConnector = new React Socket TcpConnector ( null , [
' bindto ' => ' 192.168.0.1:0 '
]);
Beachten Sie, dass Sie mit dieser Klasse nur eine Verbindung zu IP-Port-Kombinationen herstellen können. Wenn der angegebene URI ungültig ist, keine gültige IP-Adresse und keinen gültigen Port enthält oder ein anderes Schema enthält, wird er mit einer InvalidArgumentException
abgelehnt:
Wenn der angegebene URI gültig zu sein scheint, die Verbindung zu ihm jedoch fehlschlägt (z. B. wenn der Remote-Host die Verbindung ablehnt usw.), wird er mit einer RuntimeException
abgelehnt.
Wenn Sie eine Verbindung zu Hostname-Port-Kombinationen herstellen möchten, lesen Sie auch das folgende Kapitel.
Erweiterte Verwendung: Intern weist der
TcpConnector
jeder Stream-Ressource eine leere Kontextressource zu. Wenn der Ziel-URI einenhostname
Abfrageparameter enthält, wird sein Wert zum Einrichten des TLS-Peer-Namens verwendet. Dies wird vonSecureConnector
undDnsConnector
zur Überprüfung des Peer-Namens verwendet und kann auch verwendet werden, wenn Sie einen benutzerdefinierten TLS-Peer-Namen wünschen.
Die HappyEyeBallsConnector
-Klasse implementiert das ConnectorInterface
und ermöglicht Ihnen das Erstellen von Klartext-TCP/IP-Verbindungen zu jeder Hostname-Port-Kombination. Intern implementiert es den Happy-Eyeballs-Algorithmus von RFC6555
und RFC8305
um IPv6- und IPv4-Hostnamen zu unterstützen.
Dazu wird eine bestimmte TcpConnector
Instanz so dekoriert, dass sie zuerst den angegebenen Domänennamen über DNS sucht (falls zutreffend) und dann die zugrunde liegende TCP/IP-Verbindung zur aufgelösten Ziel-IP-Adresse herstellt.
Stellen Sie sicher, dass Sie Ihren DNS-Resolver und den zugrunde liegenden TCP-Connector wie folgt einrichten:
$ dnsResolverFactory = new React Dns Resolver Factory ();
$ dns = $ dnsResolverFactory -> createCached ( ' 8.8.8.8 ' );
$ dnsConnector = new React Socket HappyEyeBallsConnector ( null , $ tcpConnector , $ dns );
$ dnsConnector -> connect ( ' www.google.com:80 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
Siehe auch die Beispiele.
Ausstehende Verbindungsversuche können abgebrochen werden, indem das ausstehende Versprechen wie folgt aufgehoben wird:
$ promise = $ dnsConnector -> connect ( ' www.google.com:80 ' );
$ promise -> cancel ();
Der Aufruf von cancel()
für ein ausstehendes Versprechen bricht die zugrunde liegenden DNS-Suchvorgänge und/oder die zugrunde liegenden TCP/IP-Verbindung(en) ab und lehnt das resultierende Versprechen ab.
Diese Klasse akzeptiert einen optionalen LoopInterface|null $loop
Parameter, der verwendet werden kann, um die Ereignisschleifeninstanz zu übergeben, die für dieses Objekt verwendet werden soll. Sie können hier einen null
verwenden, um die Standardschleife zu verwenden. Dieser Wert SOLLTE NICHT angegeben werden, es sei denn, Sie sind sicher, dass Sie eine bestimmte Ereignisschleifeninstanz explizit verwenden möchten.
Erweiterte Verwendung: Intern verlässt sich der
HappyEyeBallsConnector
auf einenResolver
um die IP-Adressen für den angegebenen Hostnamen zu suchen. Anschließend wird der Hostname im Ziel-URI durch diese IPs ersetzt, einhostname
Abfrageparameter angehängt und dieser aktualisierte URI an den zugrunde liegenden Connector übergeben. Der Happy Eye Balls-Algorithmus beschreibt die Suche nach der IPv6- und IPv4-Adresse für den angegebenen Hostnamen, sodass dieser Connector zwei DNS-Suchvorgänge für die A- und AAAA-Einträge sendet. Es verwendet dann alle IP-Adressen (sowohl v6 als auch v4) und versucht, mit einem Intervall von 50 ms dazwischen eine Verbindung zu allen herzustellen. Wechsel zwischen IPv6- und IPv4-Adressen. Wenn eine Verbindung hergestellt wird, werden alle anderen DNS-Suchen und Verbindungsversuche abgebrochen.
Die DnsConnector
-Klasse implementiert das ConnectorInterface
und ermöglicht Ihnen das Erstellen von Klartext-TCP/IP-Verbindungen zu jeder Hostname-Port-Kombination.
Dazu wird eine bestimmte TcpConnector
Instanz so dekoriert, dass sie zuerst den angegebenen Domänennamen über DNS sucht (falls zutreffend) und dann die zugrunde liegende TCP/IP-Verbindung zur aufgelösten Ziel-IP-Adresse herstellt.
Stellen Sie sicher, dass Sie Ihren DNS-Resolver und den zugrunde liegenden TCP-Connector wie folgt einrichten:
$ dnsResolverFactory = new React Dns Resolver Factory ();
$ dns = $ dnsResolverFactory -> createCached ( ' 8.8.8.8 ' );
$ dnsConnector = new React Socket DnsConnector ( $ tcpConnector , $ dns );
$ dnsConnector -> connect ( ' www.google.com:80 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
Siehe auch die Beispiele.
Ausstehende Verbindungsversuche können abgebrochen werden, indem das ausstehende Versprechen wie folgt aufgehoben wird:
$ promise = $ dnsConnector -> connect ( ' www.google.com:80 ' );
$ promise -> cancel ();
Der Aufruf von cancel()
für ein ausstehendes Versprechen bricht die zugrunde liegende DNS-Suche und/oder die zugrunde liegende TCP/IP-Verbindung ab und lehnt das resultierende Versprechen ab.
Erweiterte Verwendung: Intern verlässt sich der
DnsConnector
auf einReactDnsResolverResolverInterface
um die IP-Adresse für den angegebenen Hostnamen zu suchen. Anschließend wird der Hostname im Ziel-URI durch diese IP ersetzt, einhostname
Abfrageparameter angehängt und dieser aktualisierte URI an den zugrunde liegenden Connector übergeben. Der zugrunde liegende Connector ist somit für die Herstellung einer Verbindung zur Ziel-IP-Adresse verantwortlich, während dieser Abfrageparameter zur Überprüfung des ursprünglichen Hostnamens verwendet werden kann und vomTcpConnector
zur Einrichtung des TLS-Peer-Namens verwendet wird. Wenn einhostname
explizit angegeben wird, wird dieser Abfrageparameter nicht geändert, was nützlich sein kann, wenn Sie einen benutzerdefinierten TLS-Peernamen wünschen.
Die SecureConnector
-Klasse implementiert das ConnectorInterface
und ermöglicht Ihnen die Erstellung sicherer TLS-Verbindungen (früher bekannt als SSL) zu jeder Hostname-Port-Kombination.
Dazu wird eine bestimmte DnsConnector
Instanz so dekoriert, dass sie zunächst eine Klartext-TCP/IP-Verbindung erstellt und dann die TLS-Verschlüsselung für diesen Stream aktiviert.
$ secureConnector = new React Socket SecureConnector ( $ dnsConnector );
$ secureConnector -> connect ( ' www.google.com:443 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( " GET / HTTP/1.0 rn Host: www.google.com rnrn" );
. . .
});
Siehe auch die Beispiele.
Ausstehende Verbindungsversuche können abgesagt werden, indem das anhängige Versprechen wie SO storniert wird:
$ promise = $ secureConnector -> connect ( ' www.google.com:443 ' );
$ promise -> cancel ();
Anrufen cancel()
Auf einem ausstehenden Versprechen wird die zugrunde liegende TCP/IP -Verbindung und/oder die SSL/TLS -Verhandlung storniert und das resultierende Versprechen ablehnen.
Diese Klasse nimmt ein optionales LoopInterface|null $loop
-Parameter an, mit dem die Ereignisschleifinstanz für dieses Objekt verwendet werden kann. Sie können hier einen null
verwenden, um die Standardschleife zu verwenden. Dieser Wert sollte nicht angegeben werden, es sei denn, Sie möchten sicher eine bestimmte Ereignisschleifinstanz verwenden.
Sie können optional zusätzliche SSL -Kontextoptionen an den Konstruktor wie folgt übergeben:
$ secureConnector = new React Socket SecureConnector ( $ dnsConnector , null , [
' verify_peer ' => false ,
' verify_peer_name ' => false
]);
Standardmäßig unterstützt dieser Anschluss TLSV1.0+ und schließt die Unterstützung für Legacy SSLV2/SSLV3 aus. Sie können auch explizit die TLS -Version auswählen, die Sie mit der Remote -Seite verhandeln möchten:
$ secureConnector = new React Socket SecureConnector ( $ dnsConnector , null , [
' crypto_method ' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
]);
Erweiterte Nutzung: Innen ist der
SecureConnector
auf die Einrichtung der erforderlichen Kontextoptionen für die zugrunde liegende Stream -Ressource angewiesen. Es sollte daher mit einemTcpConnector
irgendwo im Connector -Stapel verwendet werden, damit es eine leere Kontextressource für jede Stream -Ressource zuweisen und den Peer -Namen überprüfen kann. Wenn dies nicht der Fall ist, kann dies zu einem TLS -Peer -Namen -Nichtübereinstimmungsfehler oder einer schwer zu verfolgenden Rennbedingungen führen, da alle Stream -Ressourcen ansonsten eine einzelne, gemeinsam genutzte Standardkontextressource verwenden.
Die TimeoutConnector
-Klasse implementiert das ConnectorInterface
und ermöglicht es Ihnen, jeder vorhandenen Connector -Instanz Timeout -Handhabung hinzuzufügen.
Dies geschieht, indem eine bestimmte ConnectorInterface
-Instanz dekoriert und einen Timer gestartet wird, der automatisch einen zugrunde liegenden Verbindungsversuch ablehnt und abbricht, wenn es zu lange dauert.
$ timeoutConnector = new React Socket TimeoutConnector ( $ connector , 3.0 );
$ timeoutConnector -> connect ( ' google.com:80 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
// connection succeeded within 3.0 seconds
});
Siehe auch eines der Beispiele.
Diese Klasse nimmt ein optionales LoopInterface|null $loop
-Parameter an, mit dem die Ereignisschleifinstanz für dieses Objekt verwendet werden kann. Sie können hier einen null
verwenden, um die Standardschleife zu verwenden. Dieser Wert sollte nicht angegeben werden, es sei denn, Sie möchten sicher eine bestimmte Ereignisschleifinstanz verwenden.
Ausstehende Verbindungsversuche können abgesagt werden, indem das anhängige Versprechen wie SO storniert wird:
$ promise = $ timeoutConnector -> connect ( ' google.com:80 ' );
$ promise -> cancel ();
Das Aufrufen von cancel()
in einem ausstehenden Versprechen wird den zugrunde liegenden Verbindungsversuch absagen, den Timer abbrechen und das resultierende Versprechen ablehnen.
Die UnixConnector
-Klasse implementiert das ConnectorInterface
und ermöglicht es Ihnen, eine Verbindung zu UDS -Pfaden (UNIX Domain Socket) wie folgt herzustellen:
$ connector = new React Socket UnixConnector ();
$ connector -> connect ( ' /tmp/demo.sock ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( " HELLO n" );
});
Die Verbindung zu UNIX -Domänen -Sockets ist eine atomare Operation, dh das Versprechen wird sofort festgelegt (entweder auflösen oder ablehnen). Daher hat die Aufruf von cancel()
über das resultierende Versprechen keine Auswirkung.
Die
getRemoteAddress()
-Methode gibt den Pfad der Target Unix Domain Socket (UDS) wie an dieconnect()
-Methode zurück, die mit demunix://
-Schema vorbereitet ist, z. B.unix:///tmp/demo.sock
. DiegetLocalAddress()
-Methode gibt höchstwahrscheinlich einennull
zurück, da dieser Wert hier nicht für UDS -Verbindungen anwendbar ist.
Diese Klasse nimmt ein optionales LoopInterface|null $loop
-Parameter an, mit dem die Ereignisschleifinstanz für dieses Objekt verwendet werden kann. Sie können hier einen null
verwenden, um die Standardschleife zu verwenden. Dieser Wert sollte nicht angegeben werden, es sei denn, Sie möchten sicher eine bestimmte Ereignisschleifinstanz verwenden.
Die FixedUriConnector
-Klasse implementiert das ConnectorInterface
und dekoriert einen vorhandenen Anschluss, um immer einen festen, vorkonfigurierten URI zu verwenden.
Dies kann für Verbraucher nützlich sein, die bestimmte URIs nicht unterstützen, z.
$ connector = new React Socket FixedUriConnector (
' unix:///var/run/docker.sock ' ,
new React Socket UnixConnector ()
);
// destination will be ignored, actually connects to Unix domain socket
$ promise = $ connector -> connect ( ' localhost:80 ' );
Die empfohlene Methode zur Installation dieser Bibliothek ist Composer. Neu bei Composer?
Nach der Veröffentlichung wird dieses Projekt SemVer folgen. Im Moment wird dadurch die neueste Entwicklungsversion installiert:
composer require react/socket:^3@dev
Einzelheiten zu Versionsaktualisierungen finden Sie auch im CHANGELOG.
Dieses Projekt zielt darauf ab, auf jeder Plattform ausgeführt zu werden, erfordert daher keine PHP-Erweiterungen und unterstützt die Ausführung auf PHP 7.1 bis zum aktuellen PHP 8+. Es wird dringend empfohlen, für dieses Projekt die neueste unterstützte PHP-Version zu verwenden .
Legacy PHP <7.3.3 (und PHP <7.2.15) leidet unter einem Fehler, bei dem FeoF () mit einer 100% igen CPU -Verwendung auf fragmentierten TLS -Datensätzen blockiert werden kann. Wir versuchen, dies zu bearbeiten, indem wir den vollständigen Empfangspuffer gleichzeitig konsumieren, um abgestandene Daten in TLS -Puffern zu vermeiden. Es ist bekannt, dass dies mit hoher CPU-Nutzung für gutbebende Kollegen umgeht. Dies kann jedoch sehr große Datenbrocken für Szenarien mit hohem Durchsatz verursachen. Das Fehlerverhalten kann aufgrund von Netzwerk -E/A -Puffern oder böswilligen Kollegen auf betroffenen Versionen weiterhin ausgelöst werden. Die Upgrade wird dringend empfohlen.
Legacy PHP <7.1.4 leidet unter einem Fehler, wenn große Datenbrocken über TLS -Streams gleichzeitig geschrieben werden. Wir versuchen, dies zu umgehen, indem wir die Schreibgröße nur für ältere PHP -Versionen auf 8192 Bytes einschränken. Dies ist nur eine Arbeit und hat eine bemerkenswerte Leistungsstrafe für betroffene Versionen.
Um die Testsuite auszuführen, müssen Sie zunächst dieses Repo klonen und dann alle Abhängigkeiten über Composer installieren:
composer install
Um die Testsuite auszuführen, gehen Sie zum Projektstammverzeichnis und führen Sie Folgendes aus:
vendor/bin/phpunit
Die Testsuite enthält auch eine Reihe von funktionalen Integrationstests, die auf einer stabilen Internetverbindung beruhen. Wenn Sie diese nicht ausführen möchten, können sie einfach so übersprungen werden:
vendor/bin/phpunit --exclude-group internet
MIT, siehe LICENSE-Datei.