Connexions TCP/IP asynchrones, streaming en clair et serveur de socket TLS sécurisé et connexions client pour ReactPHP.
Version de développement : cette branche contient le code de la prochaine version v3. Pour le code de la version stable v1 actuelle, consultez la branche
1.x
La prochaine version v3 sera la voie à suivre pour ce package. Cependant, nous prendrons toujours activement en charge la v1 pour ceux qui ne disposent pas encore de la dernière version. Voir également les instructions d'installation pour plus de détails.
La bibliothèque de sockets fournit des interfaces réutilisables pour un serveur et un client de couche socket basés sur les composants EventLoop
et Stream
. Son composant serveur vous permet de créer des serveurs réseau qui acceptent les connexions entrantes des clients réseau (tels qu'un serveur HTTP). Son composant client vous permet de créer des clients réseau qui établissent des connexions sortantes vers des serveurs réseau (tels qu'un client HTTP ou de base de données). Cette bibliothèque fournit des moyens de streaming asynchrones pour tout cela, afin que vous puissiez gérer plusieurs connexions simultanées sans blocage.
Table des matières
Voici un serveur qui ferme la connexion si vous lui envoyez quelque chose :
$ 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 ();
});
});
Voir aussi les exemples.
Voici un client qui génère la sortie dudit serveur et tente ensuite de lui envoyer une chaîne :
$ 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 ;
});
ConnectionInterface
est utilisé pour représenter toute connexion entrante et sortante, telle qu'une connexion TCP/IP normale.
Une connexion entrante ou sortante est un flux duplex (à la fois lisible et inscriptible) qui implémente DuplexStreamInterface
de React. Il contient des propriétés supplémentaires pour l'adresse locale et distante (IP client) à partir de laquelle cette connexion a été établie.
Le plus souvent, les instances implémentant cette ConnectionInterface
sont émises par toutes les classes implémentant ServerInterface
et utilisées par toutes les classes implémentant ConnectorInterface
.
Étant donné que ConnectionInterface
implémente la DuplexStreamInterface
sous-jacente, vous pouvez utiliser n'importe lequel de ses événements et méthodes comme d'habitude :
$ 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 ();
// …
Pour plus de détails, consultez DuplexStreamInterface
.
La méthode getRemoteAddress(): ?string
renvoie l'adresse distante complète (URI) avec laquelle cette connexion a été établie.
$ address = $ connection -> getRemoteAddress ();
echo ' Connection with ' . $ address . PHP_EOL ;
Si l'adresse distante ne peut pas être déterminée ou est inconnue à ce moment (comme après la fermeture de la connexion), elle PEUT retourner une valeur NULL
à la place.
Sinon, il renverra l'adresse complète (URI) sous forme de valeur de chaîne, telle que tcp://127.0.0.1:8080
, tcp://[::1]:80
, tls://127.0.0.1:443
, unix://example.sock
ou unix:///path/to/example.sock
. Notez que les composants URI individuels sont spécifiques à l’application et dépendent du protocole de transport sous-jacent.
S'il s'agit d'une connexion basée sur TCP/IP et que vous souhaitez uniquement l'adresse IP distante, vous pouvez utiliser quelque chose comme ceci :
$ address = $ connection -> getRemoteAddress ();
$ ip = trim ( parse_url ( $ address , PHP_URL_HOST ), ' [] ' );
echo ' Connection with ' . $ ip . PHP_EOL ;
La méthode getLocalAddress(): ?string
renvoie l'adresse locale complète (URI) avec laquelle cette connexion a été établie.
$ address = $ connection -> getLocalAddress ();
echo ' Connection with ' . $ address . PHP_EOL ;
Si l'adresse locale ne peut pas être déterminée ou est inconnue à ce moment (comme après la fermeture de la connexion), elle PEUT retourner une valeur NULL
à la place.
Sinon, il renverra l'adresse complète (URI) sous forme de valeur de chaîne, telle que tcp://127.0.0.1:8080
, tcp://[::1]:80
, tls://127.0.0.1:443
, unix://example.sock
ou unix:///path/to/example.sock
. Notez que les composants URI individuels sont spécifiques à l’application et dépendent du protocole de transport sous-jacent.
Cette méthode complète la méthode getRemoteAddress()
, il ne faut donc pas les confondre.
Si votre instance TcpServer
écoute sur plusieurs interfaces (par exemple en utilisant l'adresse 0.0.0.0
), vous pouvez utiliser cette méthode pour savoir quelle interface a réellement accepté cette connexion (comme une interface publique ou locale).
Si votre système dispose de plusieurs interfaces (par exemple une interface WAN et une interface LAN), vous pouvez utiliser cette méthode pour savoir quelle interface a été réellement utilisée pour cette connexion.
ServerInterface
est chargé de fournir une interface permettant d'accepter les connexions de streaming entrantes, telles qu'une connexion TCP/IP normale.
La plupart des composants de niveau supérieur (tels qu'un serveur HTTP) acceptent une instance implémentant cette interface pour accepter les connexions de streaming entrantes. Cela se fait généralement via l'injection de dépendances, il est donc assez simple d'échanger cette implémentation contre toute autre implémentation de cette interface. Cela signifie que vous DEVRIEZ taper un indice sur cette interface au lieu d'une implémentation concrète de cette interface.
En plus de définir quelques méthodes, cette interface implémente également l' EventEmitterInterface
qui permet de réagir à certains événements.
L'événement connection
sera émis à chaque fois qu'une nouvelle connexion sera établie, c'est à dire qu'un nouveau client se connectera à ce socket serveur :
$ socket -> on ( ' connection ' , function ( React Socket ConnectionInterface $ connection ) {
echo ' new connection ' . PHP_EOL ;
});
Voir également ConnectionInterface
pour plus de détails sur la gestion de la connexion entrante.
L'événement error
sera émis chaque fois qu'il y aura une erreur lors de l'acceptation d'une nouvelle connexion d'un client.
$ socket -> on ( ' error ' , function ( Exception $ e ) {
echo ' error: ' . $ e -> getMessage () . PHP_EOL ;
});
Notez qu'il ne s'agit pas d'un événement d'erreur fatale, c'est-à-dire que le serveur continue d'écouter de nouvelles connexions même après cet événement.
La méthode getAddress(): ?string
peut être utilisée pour renvoyer l'adresse complète (URI) sur laquelle ce serveur écoute actuellement.
$ address = $ socket -> getAddress ();
echo ' Server listening on ' . $ address . PHP_EOL ;
Si l'adresse ne peut pas être déterminée ou est inconnue à ce moment (comme après la fermeture du socket), elle PEUT retourner une valeur NULL
à la place.
Sinon, il renverra l'adresse complète (URI) sous forme de valeur de chaîne, telle que tcp://127.0.0.1:8080
, tcp://[::1]:80
, tls://127.0.0.1:443
unix://example.sock
ou unix:///path/to/example.sock
. Notez que les composants URI individuels sont spécifiques à l’application et dépendent du protocole de transport sous-jacent.
S'il s'agit d'un serveur basé sur TCP/IP et que vous souhaitez uniquement le port local, vous pouvez utiliser quelque chose comme ceci :
$ address = $ socket -> getAddress ();
$ port = parse_url ( $ address , PHP_URL_PORT );
echo ' Server listening on port ' . $ port . PHP_EOL ;
La méthode pause(): void
peut être utilisée pour suspendre l'acceptation de nouvelles connexions entrantes.
Supprime la ressource socket de EventLoop et cesse ainsi d'accepter de nouvelles connexions. Notez que la socket d'écoute reste active et n'est pas fermée.
Cela signifie que les nouvelles connexions entrantes resteront en attente dans le backlog du système d'exploitation jusqu'à ce que son backlog configurable soit comblé. Une fois le retard comblé, le système d'exploitation peut rejeter d'autres connexions entrantes jusqu'à ce que le retard soit à nouveau épuisé en reprenant l'acceptation de nouvelles connexions.
Une fois le serveur mis en pause, aucun autre événement connection
NE DEVRAIT être émis.
$ socket -> pause ();
$ socket -> on ( ' connection ' , assertShouldNeverCalled ());
Cette méthode est uniquement consultative, bien qu'elle ne soit généralement pas recommandée, le serveur PEUT continuer à émettre des événements connection
.
Sauf indication contraire, un serveur ouvert avec succès NE DEVRAIT PAS démarrer en état de pause.
Vous pouvez continuer à traiter les événements en appelant à nouveau resume()
.
Notez que les deux méthodes peuvent être appelées un nombre illimité de fois, en particulier appeler pause()
plus d'une fois NE DEVRAIT PAS avoir d'effet. De même, appeler ceci après close()
est un NO-OP.
La méthode resume(): void
peut être utilisée pour reprendre l'acceptation de nouvelles connexions entrantes.
Rattachez la ressource socket à EventLoop après une précédente pause()
.
$ socket -> pause ();
Loop:: addTimer ( 1.0 , function () use ( $ socket ) {
$ socket -> resume ();
});
Notez que les deux méthodes peuvent être appelées un nombre illimité de fois, en particulier l'appel resume()
sans pause()
préalable NE DEVRAIT PAS avoir d'effet. De même, appeler ceci après close()
est un NO-OP.
La méthode close(): void
peut être utilisée pour arrêter ce socket d’écoute.
Cela cessera d’écouter les nouvelles connexions entrantes sur ce socket.
echo ' Shutting down server socket ' . PHP_EOL ;
$ socket -> close ();
Appeler cette méthode plusieurs fois sur la même instance est un NO-OP.
La classe SocketServer
est la classe principale de ce package qui implémente ServerInterface
et vous permet d'accepter les connexions de streaming entrantes, telles que TCP/IP en texte brut ou les flux de connexion TLS sécurisés.
Afin d'accepter les connexions TCP/IP en texte clair, vous pouvez simplement transmettre une combinaison d'hôte et de port comme celle-ci :
$ socket = new React Socket SocketServer ( ' 127.0.0.1:8080 ' );
L'écoute sur l'adresse localhost 127.0.0.1
signifie qu'elle ne sera pas accessible de l'extérieur de ce système. Afin de changer l'hôte sur lequel le socket écoute, vous pouvez fournir l'adresse IP d'une interface ou utiliser l'adresse spéciale 0.0.0.0
pour écouter sur toutes les interfaces :
$ socket = new React Socket SocketServer ( ' 0.0.0.0:8080 ' );
Si vous souhaitez écouter sur une adresse IPv6, vous DEVEZ mettre l'hôte entre crochets :
$ socket = new React Socket SocketServer ( ' [::1]:8080 ' );
Afin d'utiliser une attribution de port aléatoire, vous pouvez utiliser le port 0
:
$ socket = new React Socket SocketServer ( ' 127.0.0.1:0 ' );
$ address = $ socket -> getAddress ();
Pour écouter sur un chemin de socket de domaine Unix (UDS), vous DEVEZ préfixer l'URI avec le schéma unix://
:
$ socket = new React Socket SocketServer ( ' unix:///tmp/server.sock ' );
Afin d'écouter un numéro de descripteur de fichier (FD) existant, vous DEVEZ préfixer l'URI avec php://fd/
comme ceci :
$ socket = new React Socket SocketServer ( ' php://fd/3 ' );
Si l'URI donné n'est pas valide, ne contient pas de port, aucun autre schéma ou s'il contient un nom d'hôte, il lancera une InvalidArgumentException
:
// throws InvalidArgumentException due to missing port
$ socket = new React Socket SocketServer ( ' 127.0.0.1 ' );
Si l'URI donné semble valide, mais que son écoute échoue (par exemple si le port est déjà utilisé ou si un port inférieur à 1024 peut nécessiter un accès root, etc.), il lancera une RuntimeException
:
$ 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 ' );
Notez que ces conditions d'erreur peuvent varier en fonction de votre système et/ou de votre configuration. Consultez le message et le code d'exception pour plus de détails sur la condition d'erreur réelle.
Facultativement, vous pouvez spécifier les options de contexte de socket TCP pour la ressource de socket de flux sous-jacente, comme ceci :
$ socket = new React Socket SocketServer ( ' [::1]:8080 ' , [
' tcp ' => [
' backlog ' => 200 ,
' so_reuseport ' => true ,
' ipv6_v6only ' => true
]
]);
Notez que les options de contexte de socket disponibles, leurs valeurs par défaut et les effets de leur modification peuvent varier en fonction de votre système et/ou de la version de PHP. Passer des options de contexte inconnues n'a aucun effet. L'option de contexte
backlog
est par défaut511
, sauf indication explicite.
Vous pouvez démarrer un serveur TLS sécurisé (anciennement SSL) en ajoutant simplement le schéma d'URI tls://
. En interne, il attendra les connexions TCP/IP en texte clair, puis effectuera une négociation TLS pour chaque connexion. Il nécessite donc des options de contexte TLS valides, qui, dans sa forme la plus basique, peuvent ressembler à ceci si vous utilisez un fichier de certificat codé PEM :
$ socket = new React Socket SocketServer ( ' tls://127.0.0.1:8080 ' , [
' tls ' => [
' local_cert ' => ' server.pem '
]
]);
Notez que le fichier de certificat ne sera pas chargé lors de l'instanciation mais lorsqu'une connexion entrante initialise son contexte TLS. Cela implique que tout chemin ou contenu de fichier de certificat non valide ne provoquera un événement
error
que ultérieurement.
Si votre clé privée est chiffrée avec une phrase secrète, vous devez la spécifier comme ceci :
$ socket = new React Socket SocketServer ( ' tls://127.0.0.1:8000 ' , [
' tls ' => [
' local_cert ' => ' server.pem ' ,
' passphrase ' => ' secret '
]
]);
Par défaut, ce serveur prend en charge TLSv1.0+ et exclut la prise en charge de l'ancien SSLv2/SSLv3. Vous pouvez également choisir explicitement la version TLS que vous souhaitez négocier avec le côté distant :
$ socket = new React Socket SocketServer ( ' tls://127.0.0.1:8000 ' , [
' tls ' => [
' local_cert ' => ' server.pem ' ,
' crypto_method ' => STREAM_CRYPTO_METHOD_TLSv1_2_SERVER
]
]);
Notez que les options de contexte TLS disponibles, leurs valeurs par défaut et les effets de leur modification peuvent varier en fonction de votre système et/ou de la version de PHP. Le tableau de contexte externe vous permet également d'utiliser simultanément les options de contexte
tcp
(et éventuellement plus). Passer des options de contexte inconnues n'a aucun effet. Si vous n'utilisez pas le schématls://
, la transmission des options de contextetls
n'a aucun effet.
Chaque fois qu'un client se connecte, il émettra un événement connection
avec une instance de connexion implémentant ConnectionInterface
:
$ socket -> on ( ' connection ' , function ( React Socket ConnectionInterface $ connection ) {
echo ' Plaintext connection from ' . $ connection -> getRemoteAddress () . PHP_EOL ;
$ connection -> write ( ' hello there! ' . PHP_EOL );
…
});
Voir également ServerInterface
pour plus de détails.
Cette classe prend un paramètre facultatif LoopInterface|null $loop
qui peut être utilisé pour transmettre l'instance de boucle d'événement à utiliser pour cet objet. Vous pouvez utiliser ici une valeur null
afin d'utiliser la boucle par défaut. Cette valeur NE DEVRAIT PAS être donnée sauf si vous êtes sûr de vouloir utiliser explicitement une instance de boucle d'événement donnée.
Notez que la classe
SocketServer
est une implémentation concrète pour les sockets TCP/IP. Si vous souhaitez saisir un indice dans l'implémentation de votre protocole de niveau supérieur, vous DEVEZ plutôt utiliser l'ServerInterface
générique.
La classe TcpServer
implémente ServerInterface
et est responsable de l'acceptation des connexions TCP/IP en texte brut.
$ server = new React Socket TcpServer ( 8080 );
Comme ci-dessus, le paramètre $uri
ne peut consister qu'en un port, auquel cas le serveur écoutera par défaut sur l'adresse localhost 127.0.0.1
, ce qui signifie qu'il ne sera pas accessible de l'extérieur de ce système.
Afin d'utiliser une attribution de port aléatoire, vous pouvez utiliser le port 0
:
$ server = new React Socket TcpServer ( 0 );
$ address = $ server -> getAddress ();
Afin de changer l'hôte sur lequel le socket écoute, vous pouvez fournir une adresse IP via le premier paramètre fourni au constructeur, éventuellement précédé du schéma tcp://
:
$ server = new React Socket TcpServer ( ' 192.168.0.1:8080 ' );
Si vous souhaitez écouter sur une adresse IPv6, vous DEVEZ mettre l'hôte entre crochets :
$ server = new React Socket TcpServer ( ' [::1]:8080 ' );
Si l'URI donné n'est pas valide, ne contient pas de port, aucun autre schéma ou s'il contient un nom d'hôte, il lancera une InvalidArgumentException
:
// throws InvalidArgumentException due to missing port
$ server = new React Socket TcpServer ( ' 127.0.0.1 ' );
Si l'URI donné semble valide, mais que son écoute échoue (par exemple si le port est déjà utilisé ou si un port inférieur à 1024 peut nécessiter un accès root, etc.), il lancera une RuntimeException
:
$ first = new React Socket TcpServer ( 8080 );
// throws RuntimeException because port is already in use
$ second = new React Socket TcpServer ( 8080 );
Notez que ces conditions d'erreur peuvent varier en fonction de votre système et/ou de votre configuration. Consultez le message et le code d'exception pour plus de détails sur la condition d'erreur réelle.
Cette classe prend un paramètre facultatif LoopInterface|null $loop
qui peut être utilisé pour transmettre l'instance de boucle d'événement à utiliser pour cet objet. Vous pouvez utiliser ici une valeur null
afin d'utiliser la boucle par défaut. Cette valeur NE DEVRAIT PAS être donnée sauf si vous êtes sûr de vouloir utiliser explicitement une instance de boucle d'événement donnée.
Facultativement, vous pouvez spécifier des options de contexte de socket pour la ressource de socket de flux sous-jacente comme ceci :
$ server = new React Socket TcpServer ( ' [::1]:8080 ' , null , [
' backlog ' => 200 ,
' so_reuseport ' => true ,
' ipv6_v6only ' => true
]);
Notez que les options de contexte de socket disponibles, leurs valeurs par défaut et les effets de leur modification peuvent varier en fonction de votre système et/ou de la version de PHP. Passer des options de contexte inconnues n'a aucun effet. L'option de contexte
backlog
est par défaut511
, sauf indication contraire explicite.
Chaque fois qu'un client se connecte, il émettra un événement connection
avec une instance de connexion implémentant ConnectionInterface
:
$ server -> on ( ' connection ' , function ( React Socket ConnectionInterface $ connection ) {
echo ' Plaintext connection from ' . $ connection -> getRemoteAddress () . PHP_EOL ;
$ connection -> write ( ' hello there! ' . PHP_EOL );
…
});
Voir également ServerInterface
pour plus de détails.
La classe SecureServer
implémente ServerInterface
et est chargée de fournir un serveur TLS (anciennement SSL) sécurisé.
Pour ce faire, il encapsule une instance TcpServer
qui attend les connexions TCP/IP en texte brut, puis effectue une négociation TLS pour chaque connexion. Il nécessite donc des options de contexte TLS valides, qui, dans sa forme la plus basique, peuvent ressembler à ceci si vous utilisez un fichier de certificat codé PEM :
$ server = new React Socket TcpServer ( 8000 );
$ server = new React Socket SecureServer ( $ server , null , [
' local_cert ' => ' server.pem '
]);
Notez que le fichier de certificat ne sera pas chargé lors de l'instanciation mais lorsqu'une connexion entrante initialise son contexte TLS. Cela implique que tout chemin ou contenu de fichier de certificat non valide ne provoquera un événement
error
que ultérieurement.
Si votre clé privée est chiffrée avec une phrase secrète, vous devez la spécifier comme ceci :
$ server = new React Socket TcpServer ( 8000 );
$ server = new React Socket SecureServer ( $ server , null , [
' local_cert ' => ' server.pem ' ,
' passphrase ' => ' secret '
]);
Par défaut, ce serveur prend en charge TLSv1.0+ et exclut la prise en charge de l'ancien SSLv2/SSLv3. Vous pouvez également choisir explicitement la version TLS que vous souhaitez négocier avec le côté distant :
$ 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
]);
Notez que les options de contexte TLS disponibles, leurs valeurs par défaut et les effets de leur modification peuvent varier en fonction de votre système et/ou de la version de PHP. Passer des options de contexte inconnues n'a aucun effet.
Chaque fois qu'un client termine la négociation TLS, il émettra un événement connection
avec une instance de connexion implémentant ConnectionInterface
:
$ server -> on ( ' connection ' , function ( React Socket ConnectionInterface $ connection ) {
echo ' Secure connection from ' . $ connection -> getRemoteAddress () . PHP_EOL ;
$ connection -> write ( ' hello there! ' . PHP_EOL );
…
});
Chaque fois qu'un client ne parvient pas à effectuer une négociation TLS réussie, il émet un événement error
, puis ferme la connexion TCP/IP sous-jacente :
$ server -> on ( ' error ' , function ( Exception $ e ) {
echo ' Error ' . $ e -> getMessage () . PHP_EOL ;
});
Voir également ServerInterface
pour plus de détails.
Notez que la classe SecureServer
est une implémentation concrète pour les sockets TLS. Si vous souhaitez saisir un indice dans l'implémentation de votre protocole de niveau supérieur, vous DEVEZ plutôt utiliser l' ServerInterface
générique.
Cette classe prend un paramètre facultatif LoopInterface|null $loop
qui peut être utilisé pour transmettre l'instance de boucle d'événement à utiliser pour cet objet. Vous pouvez utiliser ici une valeur null
afin d'utiliser la boucle par défaut. Cette valeur NE DEVRAIT PAS être donnée sauf si vous êtes sûr de vouloir utiliser explicitement une instance de boucle d'événement donnée.
Utilisation avancée : même si vous autorisez n'importe quelle
ServerInterface
comme premier paramètre, vous DEVEZ transmettre une instanceTcpServer
comme premier paramètre, à moins que vous ne sachiez ce que vous faites. En interne,SecureServer
doit définir les options de contexte TLS requises sur les ressources de flux sous-jacentes. Ces ressources ne sont exposées via aucune des interfaces définies dans ce package, mais uniquement via la classeConnection
interne. La classeTcpServer
est garantie d'émettre des connexions qui implémententConnectionInterface
et utilise la classeConnection
interne afin d'exposer ces ressources sous-jacentes. Si vous utilisez uneServerInterface
personnalisée et que son événementconnection
ne répond pas à cette exigence,SecureServer
émettra un événementerror
, puis fermera la connexion sous-jacente.
La classe UnixServer
implémente ServerInterface
et est responsable de l'acceptation des connexions sur les sockets de domaine Unix (UDS).
$ server = new React Socket UnixServer ( ' /tmp/server.sock ' );
Comme ci-dessus, le paramètre $uri
ne peut consister qu'en un chemin de socket ou un chemin de socket préfixé par le schéma unix://
.
Si l'URI donné semble valide, mais que son écoute échoue (par exemple si le socket est déjà utilisé ou si le fichier n'est pas accessible, etc.), il lancera une RuntimeException
:
$ first = new React Socket UnixServer ( ' /tmp/same.sock ' );
// throws RuntimeException because socket is already in use
$ second = new React Socket UnixServer ( ' /tmp/same.sock ' );
Notez que ces conditions d'erreur peuvent varier en fonction de votre système et/ou de votre configuration. En particulier, Zend PHP ne signale "Erreur inconnue" que lorsque le chemin UDS existe déjà et ne peut pas être lié. Vous souhaiterez peut-être vérifier
is_file()
sur le chemin UDS donné pour signaler un message d'erreur plus convivial dans ce cas. Consultez le message et le code d'exception pour plus de détails sur la condition d'erreur réelle.
Cette classe prend un paramètre facultatif LoopInterface|null $loop
qui peut être utilisé pour transmettre l'instance de boucle d'événement à utiliser pour cet objet. Vous pouvez utiliser ici une valeur null
afin d'utiliser la boucle par défaut. Cette valeur NE DEVRAIT PAS être donnée sauf si vous êtes sûr de vouloir utiliser explicitement une instance de boucle d'événement donnée.
Chaque fois qu'un client se connecte, il émettra un événement connection
avec une instance de connexion implémentant ConnectionInterface
:
$ server -> on ( ' connection ' , function ( React Socket ConnectionInterface $ connection ) {
echo ' New connection ' . PHP_EOL ;
$ connection -> write ( ' hello there! ' . PHP_EOL );
…
});
Voir également ServerInterface
pour plus de détails.
Le décorateur LimitingServer
encapsule une ServerInterface
donnée et est responsable de la limitation et du suivi des connexions ouvertes à cette instance de serveur.
Chaque fois que le serveur sous-jacent émet un événement connection
, il vérifie ses limites puis soit
connection
error
à la place.Chaque fois qu'une connexion se ferme, cette connexion sera supprimée de la liste des connexions ouvertes.
$ server = new React Socket LimitingServer ( $ server , 100 );
$ server -> on ( ' connection ' , function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' hello there! ' . PHP_EOL );
…
});
Voir aussi le deuxième exemple pour plus de détails.
Vous devez transmettre un nombre maximum de connexions ouvertes pour garantir que le serveur rejettera (fermera) automatiquement les connexions une fois cette limite dépassée. Dans ce cas, il émettra un événement error
pour en informer et aucun événement connection
ne sera émis.
$ server = new React Socket LimitingServer ( $ server , 100 );
$ server -> on ( ' connection ' , function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' hello there! ' . PHP_EOL );
…
});
Vous POUVEZ passer une limite null
afin de ne mettre aucune limite sur le nombre de connexions ouvertes et continuer à accepter de nouvelles connexions jusqu'à ce que vous manquiez de ressources du système d'exploitation (telles que les descripteurs de fichiers ouverts). Cela peut être utile si vous ne souhaitez pas vous soucier d'appliquer une limite mais que vous souhaitez tout de même utiliser la méthode getConnections()
.
Vous pouvez éventuellement configurer le serveur pour qu'il suspende l'acceptation de nouvelles connexions une fois la limite de connexion atteinte. Dans ce cas, il mettra en pause le serveur sous-jacent et ne traitera plus aucune nouvelle connexion, ne fermant ainsi plus aucune connexion excessive. Le système d'exploitation sous-jacent est chargé de conserver un arriéré de connexions en attente jusqu'à ce que sa limite soit atteinte, moment auquel il commencera à rejeter d'autres connexions. Une fois que le serveur est en dessous de la limite de connexion, il continuera à consommer les connexions du backlog et traitera toutes les données en attente sur chaque connexion. Ce mode peut être utile pour certains protocoles conçus pour attendre un message de réponse (comme HTTP), mais peut être moins utile pour d'autres protocoles qui exigent des réponses immédiates (comme un message de « bienvenue » dans une discussion interactive).
$ server = new React Socket LimitingServer ( $ server , 100 , true );
$ server -> on ( ' connection ' , function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' hello there! ' . PHP_EOL );
…
});
La méthode getConnections(): ConnectionInterface[]
peut être utilisée pour renvoyer un tableau avec toutes les connexions actuellement actives.
foreach ( $ server -> getConnection () as $ connection ) {
$ connection -> write ( ' Hi! ' );
}
ConnectorInterface
est chargé de fournir une interface pour établir des connexions de streaming, telles qu'une connexion TCP/IP normale.
Il s'agit de l'interface principale définie dans ce package et elle est utilisée dans tout le vaste écosystème de React.
La plupart des composants de niveau supérieur (tels que HTTP, base de données ou autres clients de service réseau) acceptent une instance implémentant cette interface pour créer leur connexion TCP/IP au service réseau sous-jacent. Cela se fait généralement via l'injection de dépendances, il est donc assez simple d'échanger cette implémentation contre toute autre implémentation de cette interface.
L'interface ne propose qu'une seule méthode :
La méthode connect(string $uri): PromiseInterface<ConnectionInterface>
peut être utilisée pour créer une connexion en continu vers l'adresse distante donnée.
Il renvoie une promesse qui soit se réalise avec un flux implémentant ConnectionInterface
en cas de succès, soit est rejetée avec une Exception
si la connexion échoue :
$ connector -> connect ( ' google.com:443 ' )-> then (
function ( React Socket ConnectionInterface $ connection ) {
// connection successfully established
},
function ( Exception $ error ) {
// failed to connect due to $error
}
);
Voir également ConnectionInterface
pour plus de détails.
La promesse renvoyée DOIT être mise en œuvre de telle manière qu'elle puisse être annulée lorsqu'elle est toujours en attente. L'annulation d'une promesse en attente DOIT rejeter sa valeur avec une Exception
. Il DEVRAIT nettoyer toutes les ressources et références sous-jacentes, le cas échéant :
$ promise = $ connector -> connect ( $ uri );
$ promise -> cancel ();
La classe Connector
est la classe principale de ce package qui implémente ConnectorInterface
et vous permet de créer des connexions de streaming.
Vous pouvez utiliser ce connecteur pour créer tout type de connexions de streaming, telles que TCP/IP en texte brut, TLS sécurisé ou flux de connexion Unix local.
Il se lie à la boucle d'événement principale et peut être utilisé comme ceci :
$ 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 ;
});
Afin de créer une connexion TCP/IP en texte clair, vous pouvez simplement transmettre une combinaison d'hôte et de port comme celle-ci :
$ connector -> connect ( ' www.google.com:80 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
Si vous ne spécifiez pas de schéma d'URI dans l'URI de destination, il prendra
tcp://
par défaut et établira une connexion TCP/IP en texte brut. Notez que les connexions TCP/IP nécessitent une partie hôte et port dans l'URI de destination comme ci-dessus, tous les autres composants URI sont facultatifs.
Afin de créer une connexion TLS sécurisée, vous pouvez utiliser le schéma d'URI tls://
comme ceci :
$ connector -> connect ( ' tls://www.google.com:443 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
Afin de créer une connexion socket de domaine Unix locale, vous pouvez utiliser le schéma d'URI unix://
comme ceci :
$ connector -> connect ( ' unix:///tmp/demo.sock ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
La méthode
getRemoteAddress()
renverra le chemin du socket de domaine Unix (UDS) cible tel qu'indiqué à la méthodeconnect()
, y compris le schémaunix://
, par exempleunix:///tmp/demo.sock
. La méthodegetLocalAddress()
renverra très probablement une valeurnull
car cette valeur n'est pas applicable aux connexions UDS ici.
Sous le capot, le Connector
est implémenté comme une façade de niveau supérieur pour les connecteurs de niveau inférieur implémentés dans ce package. Cela signifie qu'il partage également toutes leurs fonctionnalités et détails de mise en œuvre. Si vous souhaitez saisir un indice dans l'implémentation de votre protocole de niveau supérieur, vous DEVEZ plutôt utiliser la ConnectorInterface
générique.
Depuis v1.4.0
, la classe Connector
utilise par défaut l'algorithme Happy Eyeballs pour se connecter automatiquement sur IPv4 ou IPv6 lorsqu'un nom d'hôte est donné. Cela tente automatiquement de se connecter en utilisant à la fois IPv4 et IPv6 (en préférant IPv6), évitant ainsi les problèmes habituels rencontrés par les utilisateurs avec des connexions ou des configurations IPv6 imparfaites. Si vous souhaitez revenir à l'ancien comportement consistant à effectuer uniquement une recherche IPv4 et à tenter une seule connexion IPv4, vous pouvez configurer le Connector
comme ceci :
$ connector = new React Socket Connector ([
' happy_eyeballs ' => false
]);
De même, vous pouvez également modifier le comportement DNS par défaut comme suit. La classe Connector
tentera de détecter les paramètres DNS de votre système (et utilise le serveur DNS public 8.8.8.8
de Google comme solution de secours si elle ne parvient pas à déterminer les paramètres de votre système) pour résoudre par défaut tous les noms d'hôte publics en adresses IP sous-jacentes. Si vous souhaitez explicitement utiliser un serveur DNS personnalisé (tel qu'un relais DNS local ou un serveur DNS à l'échelle de l'entreprise), vous pouvez configurer le Connector
comme ceci :
$ connector = new React Socket Connector ([
' dns ' => ' 127.0.1.1 '
]);
$ connector -> connect ( ' localhost:80 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
Si vous ne souhaitez pas du tout utiliser de résolveur DNS et souhaitez vous connecter uniquement aux adresses IP, vous pouvez également configurer votre Connector
comme ceci :
$ connector = new React Socket Connector ([
' dns ' => false
]);
$ connector -> connect ( ' 127.0.0.1:80 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
Avancé : si vous avez besoin d'une instance DNS ReactDnsResolverResolverInterface
personnalisée, vous pouvez également configurer votre Connector
comme ceci :
$ 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 ();
});
Par défaut, les schémas d'URI tcp://
et tls://
utiliseront une valeur de délai d'attente qui respecte votre paramètre ini default_socket_timeout
(qui est par défaut de 60 s). Si vous souhaitez une valeur de délai d'attente personnalisée, vous pouvez simplement transmettre ceci comme ceci :
$ connector = new React Socket Connector ([
' timeout ' => 10.0
]);
De même, si vous ne souhaitez pas du tout appliquer de délai d'attente et laisser le système d'exploitation gérer cela, vous pouvez passer un indicateur booléen comme celui-ci :
$ connector = new React Socket Connector ([
' timeout ' => false
]);
Par défaut, le Connector
prend en charge les schémas d'URI tcp://
, tls://
et unix://
. Si vous souhaitez interdire explicitement l'un de ces éléments, vous pouvez simplement passer des indicateurs booléens comme celui-ci :
// 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://
et tls://
acceptent également des options de contexte supplémentaires transmises aux connecteurs sous-jacents. Si vous souhaitez transmettre explicitement des options de contexte supplémentaires, vous pouvez simplement transmettre des tableaux d'options de contexte comme celui-ci :
// 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 ();
});
Par défaut, ce connecteur prend en charge TLSv1.0+ et exclut la prise en charge de l'ancien SSLv2/SSLv3. Vous pouvez également choisir explicitement la version TLS que vous souhaitez négocier avec le côté distant :
$ connector = new React Socket Connector ([
' tls ' => [
' crypto_method ' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
]
]);
Pour plus de détails sur les options de contexte, veuillez vous référer à la documentation PHP sur les options de contexte de socket et les options de contexte SSL.
Avancé : par défaut, le Connector
prend en charge les schémas d'URI tcp://
, tls://
et unix://
. Pour cela, il configure automatiquement les classes de connecteurs requises. Si vous souhaitez transmettre explicitement des connecteurs personnalisés pour l'un d'entre eux, vous pouvez simplement transmettre une instance implémentant ConnectorInterface
comme ceci :
$ 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 ();
});
En interne, le connecteur
tcp://
sera toujours encapsulé par le résolveur DNS, sauf si vous désactivez DNS comme dans l'exemple ci-dessus. Dans ce cas, le connecteurtcp://
reçoit le nom d'hôte réel au lieu de uniquement l'adresse IP résolue et est donc responsable de l'exécution de la recherche. En interne, le connecteurtls://
créé automatiquement encapsulera toujours le connecteurtcp://
sous-jacent pour établir la connexion TCP/IP en texte brut sous-jacent avant d'activer le mode TLS sécurisé. Si vous souhaitez utiliser un connecteurtcp://
sous-jacent personnalisé pour les connexions TLS sécurisées uniquement, vous pouvez explicitement transmettre un connecteurtls://
comme ci-dessus. En interne, les connecteurstcp://
ettls://
seront toujours encapsulés parTimeoutConnector
, sauf si vous désactivez les délais d'attente comme dans l'exemple ci-dessus.
Cette classe prend un paramètre facultatif LoopInterface|null $loop
qui peut être utilisé pour transmettre l'instance de boucle d'événement à utiliser pour cet objet. Vous pouvez utiliser ici une valeur null
afin d'utiliser la boucle par défaut. Cette valeur NE DEVRAIT PAS être donnée sauf si vous êtes sûr de vouloir utiliser explicitement une instance de boucle d'événement donnée.
La classe TcpConnector
implémente ConnectorInterface
et vous permet de créer des connexions TCP/IP en texte brut vers n'importe quelle combinaison de ports IP :
$ tcpConnector = new React Socket TcpConnector ();
$ tcpConnector -> connect ( ' 127.0.0.1:80 ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( ' ... ' );
$ connection -> end ();
});
Voir aussi les exemples.
Les tentatives de connexion en attente peuvent être annulées en annulant sa promesse en attente comme suit :
$ promise = $ tcpConnector -> connect ( ' 127.0.0.1:80 ' );
$ promise -> cancel ();
L'appel cancel()
sur une promesse en attente fermera la ressource socket sous-jacente, annulant ainsi la connexion TCP/IP en attente et rejettera la promesse résultante.
Cette classe prend un paramètre facultatif LoopInterface|null $loop
qui peut être utilisé pour transmettre l'instance de boucle d'événement à utiliser pour cet objet. Vous pouvez utiliser ici une valeur null
afin d'utiliser la boucle par défaut. Cette valeur NE DEVRAIT PAS être donnée sauf si vous êtes sûr de vouloir utiliser explicitement une instance de boucle d'événement donnée.
Vous pouvez éventuellement transmettre des options de contexte de socket supplémentaires au constructeur comme ceci :
$ tcpConnector = new React Socket TcpConnector ( null , [
' bindto ' => ' 192.168.0.1:0 '
]);
Notez que cette classe vous permet uniquement de vous connecter à des combinaisons de ports IP. Si l'URI donné n'est pas valide, ne contient pas d'adresse IP et de port valides ou contient tout autre schéma, il sera rejeté avec une InvalidArgumentException
:
Si l'URI donné semble valide, mais que la connexion échoue (par exemple si l'hôte distant rejette la connexion, etc.), il sera rejeté avec une RuntimeException
.
Si vous souhaitez vous connecter à des combinaisons nom d'hôte-port, consultez également le chapitre suivant.
Utilisation avancée : en interne, le
TcpConnector
alloue une ressource de contexte vide pour chaque ressource de flux. Si l'URI de destination contient un paramètre de requêtehostname
, sa valeur sera utilisée pour configurer le nom d'homologue TLS. Ceci est utilisé parSecureConnector
etDnsConnector
pour vérifier le nom de l'homologue et peut également être utilisé si vous souhaitez un nom d'homologue TLS personnalisé.
La classe HappyEyeBallsConnector
implémente ConnectorInterface
et vous permet de créer des connexions TCP/IP en texte brut vers n'importe quelle combinaison nom d'hôte-port. En interne, il implémente l'algorithme Happy Eyeballs des RFC6555
et RFC8305
pour prendre en charge les noms d'hôte IPv6 et IPv4.
Pour ce faire, il décore une instance TcpConnector
donnée afin qu'elle recherche d'abord le nom de domaine donné via DNS (le cas échéant), puis établisse la connexion TCP/IP sous-jacente à l'adresse IP cible résolue.
Assurez-vous de configurer votre résolveur DNS et votre connecteur TCP sous-jacent comme ceci :
$ 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 ();
});
Voir aussi les exemples.
Les tentatives de connexion en attente peuvent être annulées en annulant sa promesse en attente comme suit :
$ promise = $ dnsConnector -> connect ( ' www.google.com:80 ' );
$ promise -> cancel ();
L’appel cancel()
sur une promesse en attente annulera les recherches DNS sous-jacentes et/ou la ou les connexions TCP/IP sous-jacentes et rejettera la promesse résultante.
Cette classe prend un paramètre facultatif LoopInterface|null $loop
qui peut être utilisé pour transmettre l'instance de boucle d'événement à utiliser pour cet objet. Vous pouvez utiliser ici une valeur null
afin d'utiliser la boucle par défaut. Cette valeur NE DEVRAIT PAS être donnée sauf si vous êtes sûr de vouloir utiliser explicitement une instance de boucle d'événement donnée.
Utilisation avancée : en interne, le
HappyEyeBallsConnector
s'appuie sur unResolver
pour rechercher les adresses IP du nom d'hôte donné. Il remplacera ensuite le nom d'hôte dans l'URI de destination par ces adresses IP, ajoutera un paramètre de requêtehostname
et transmettra cet URI mis à jour au connecteur sous-jacent. L'algorithme Happy Eye Balls décrit la recherche des adresses IPv6 et IPv4 pour le nom d'hôte donné. Ce connecteur envoie donc deux recherches DNS pour les enregistrements A et AAAA. Il utilise ensuite toutes les adresses IP (v6 et v4) et essaie de se connecter à toutes avec un intervalle de 50 ms entre les deux. Alternance entre les adresses IPv6 et IPv4. Lorsqu'une connexion est établie, toutes les autres recherches DNS et tentatives de connexion sont annulées.
La classe DnsConnector
implémente ConnectorInterface
et vous permet de créer des connexions TCP/IP en texte brut vers n'importe quelle combinaison nom d'hôte-port.
Pour ce faire, il décore une instance TcpConnector
donnée afin qu'elle recherche d'abord le nom de domaine donné via DNS (le cas échéant), puis établisse la connexion TCP/IP sous-jacente à l'adresse IP cible résolue.
Assurez-vous de configurer votre résolveur DNS et votre connecteur TCP sous-jacent comme ceci :
$ 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 ();
});
Voir aussi les exemples.
Les tentatives de connexion en attente peuvent être annulées en annulant sa promesse en attente comme suit :
$ promise = $ dnsConnector -> connect ( ' www.google.com:80 ' );
$ promise -> cancel ();
L'appel cancel()
sur une promesse en attente annulera la recherche DNS sous-jacente et/ou la connexion TCP/IP sous-jacente et rejettera la promesse résultante.
Utilisation avancée : en interne, le
DnsConnector
s'appuie sur unReactDnsResolverResolverInterface
pour rechercher l'adresse IP du nom d'hôte donné. Il remplacera ensuite le nom d'hôte dans l'URI de destination par cette adresse IP, ajoutera un paramètre de requêtehostname
et transmettra cet URI mis à jour au connecteur sous-jacent. Le connecteur sous-jacent est ainsi responsable de la création d'une connexion à l'adresse IP cible, tandis que ce paramètre de requête peut être utilisé pour vérifier le nom d'hôte d'origine et est utilisé par leTcpConnector
pour configurer le nom du homologue TLS. Si unhostname
est donné explicitement, ce paramètre de requête ne sera pas modifié, ce qui peut être utile si vous souhaitez un nom d'homologue TLS personnalisé.
La classe SecureConnector
implémente ConnectorInterface
et vous permet de créer des connexions TLS sécurisées (anciennement appelées SSL) vers n'importe quelle combinaison nom d'hôte-port.
Pour ce faire, il décore une instance DnsConnector
donnée afin qu'elle crée d'abord une connexion TCP/IP en texte brut, puis active le cryptage TLS sur ce flux.
$ 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" );
. . .
});
Voir aussi les exemples.
Les tentatives de connexion en attente peuvent être annulées en annulant sa promesse en attente comme tel:
$ promise = $ secureConnector -> connect ( ' www.google.com:443 ' );
$ promise -> cancel ();
L'appel cancel()
sur une promesse en attente annulera la connexion TCP / IP sous-jacente et / ou la négociation SSL / TLS et rejeter la promesse résultante.
Cette classe prend un paramètre LoopInterface|null $loop
qui peut être utilisé pour transmettre l'instance de boucle d'événement à utiliser pour cet objet. Vous pouvez utiliser une valeur null
ici afin d'utiliser la boucle par défaut. Cette valeur ne doit pas être donnée, sauf si vous êtes sûr de souhaiter utiliser explicitement une instance de boucle d'événements donnée.
Vous pouvez éventuellement transmettre des options de contexte SSL supplémentaires au constructeur comme ceci:
$ secureConnector = new React Socket SecureConnector ( $ dnsConnector , null , [
' verify_peer ' => false ,
' verify_peer_name ' => false
]);
Par défaut, ce connecteur prend en charge TLSV1.0 + et exclut la prise en charge de Legacy SSLV2 / SSLV3. Vous pouvez également choisir explicitement la version TLS que vous souhaitez négocier avec le côté distant:
$ secureConnector = new React Socket SecureConnector ( $ dnsConnector , null , [
' crypto_method ' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
]);
Utilisation avancée: en interne, le
SecureConnector
s'appuie sur la configuration des options de contexte requises sur la ressource de flux sous-jacente. Il devrait être utilisé avec unTcpConnector
quelque part dans la pile de connecteur afin qu'il puisse allouer une ressource de contexte vide pour chaque ressource de flux et vérifier le nom de pair. Le défaut de le faire peut entraîner une erreur de décalage du nom de pair TLS ou des conditions de course difficiles à tracer, car toutes les ressources de flux utiliseront une seule ressource de contexte par défaut partagée autrement.
La classe TimeoutConnector
implémente le ConnectorInterface
et vous permet d'ajouter une manipulation de délai d'expiration à toute instance de connecteur existante.
Il le fait en décorant une instance ConnectorInterface
donnée et en démarrant une minuterie qui rejetera et interrompra automatiquement toute tentative de connexion sous-jacente si cela prend trop de temps.
$ 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
});
Voir aussi l'un des exemples.
Cette classe prend un paramètre LoopInterface|null $loop
qui peut être utilisé pour transmettre l'instance de boucle d'événement à utiliser pour cet objet. Vous pouvez utiliser une valeur null
ici afin d'utiliser la boucle par défaut. Cette valeur ne doit pas être donnée, sauf si vous êtes sûr de souhaiter utiliser explicitement une instance de boucle d'événements donnée.
Les tentatives de connexion en attente peuvent être annulées en annulant sa promesse en attente comme tel:
$ promise = $ timeoutConnector -> connect ( ' google.com:80 ' );
$ promise -> cancel ();
Appeler cancel()
sur une promesse en attente annulera la tentative de connexion sous-jacente, interdit la minuterie et rejettera la promesse résultante.
La classe UnixConnector
implémente le ConnectorInterface
et vous permet de vous connecter aux chemins de socket de domaine UNIX (UDS) comme celui-ci:
$ connector = new React Socket UnixConnector ();
$ connector -> connect ( ' /tmp/demo.sock ' )-> then ( function ( React Socket ConnectionInterface $ connection ) {
$ connection -> write ( " HELLO n" );
});
La connexion aux prises de domaine UNIX est une opération atomique, c'est-à-dire que sa promesse se réglera (résoudre ou rejeter) immédiatement. En tant que tel, appeler cancel()
sur la promesse résultante n'a aucun effet.
La méthode
getRemoteAddress()
renverra le chemin cible du socket de domaine UNIX (UDS) comme indiqué à la méthodeconnect()
, adjoint avec le schémaunix://
, par exempleunix:///tmp/demo.sock
. La méthodegetLocalAddress()
renvoie très probablement une valeurnull
car cette valeur n'est pas applicable aux connexions UDS ici.
Cette classe prend un paramètre LoopInterface|null $loop
qui peut être utilisé pour transmettre l'instance de boucle d'événement à utiliser pour cet objet. Vous pouvez utiliser une valeur null
ici afin d'utiliser la boucle par défaut. Cette valeur ne doit pas être donnée, sauf si vous êtes sûr de souhaiter utiliser explicitement une instance de boucle d'événements donnée.
La classe FixedUriConnector
implémente le ConnectorInterface
et décore un connecteur existant pour toujours utiliser un URI fixe et préconfiguré.
Cela peut être utile pour les consommateurs qui ne prennent pas en charge certains URI, par exemple lorsque vous souhaitez vous connecter explicitement à un chemin de socket de domaine UNIX (UDS) au lieu de vous connecter à une adresse par défaut supposée par une API de niveau supérieur:
$ 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 ' );
La méthode recommandée pour installer cette bibliothèque consiste à utiliser Composer. Nouveau sur Composer ?
Une fois publié, ce projet suivra SemVer. Pour le moment, cela installera la dernière version de développement :
composer require react/socket:^3@dev
Voir également le CHANGELOG pour plus de détails sur les mises à niveau de version.
Ce projet vise à fonctionner sur n'importe quelle plate-forme et ne nécessite donc aucune extension PHP et prend en charge l'exécution sur PHP 7.1 jusqu'à PHP 8+ actuel. Il est fortement recommandé d'utiliser la dernière version de PHP prise en charge pour ce projet.
Le PHP hérité <7.3.3 (et PHP <7.2.15) souffre d'un bogue où FEOF () pourrait bloquer avec une utilisation 100% CPU sur des enregistrements TLS fragmentés. Nous essayons de contourner cela en consommant toujours le tampon de réception complet à la fois pour éviter les données périmées dans les tampons TLS. Ceci est connu pour contourner une utilisation élevée du processeur pour les pairs bien en train de se débrouiller, mais cela peut provoquer de très grands morceaux de données pour des scénarios à haut débit. Le comportement de buggy peut toujours être déclenché en raison de tampons d'E / S de réseau ou de pairs malveillants sur des versions affectées, la mise à niveau est fortement recommandée.
Le héritage PHP <7.1.4 souffre d'un bug lors de l'écriture de gros morceaux de données sur les flux TLS à la fois. Nous essayons de contourner cela en limitant la taille du morceau d'écriture à 8192 octets pour les versions PHP plus anciennes uniquement. Il s'agit seulement d'une contournement et d'une pénalité de performance notable sur les versions affectées.
Pour exécuter la suite de tests, vous devez d'abord cloner ce dépôt, puis installer toutes les dépendances via Composer :
composer install
Pour exécuter la suite de tests, accédez à la racine du projet et exécutez :
vendor/bin/phpunit
La suite de test contient également un certain nombre de tests d'intégration fonctionnelle qui reposent sur une connexion Internet stable. Si vous ne voulez pas les exécuter, ils peuvent simplement être sautés comme ceci:
vendor/bin/phpunit --exclude-group internet
MIT, voir fichier LICENSE.