Sujet : Hoa_Socket prend du grade
Hey
,
Hoa_Socket prend du grade. En effet, j'ai ajouté le support de select(). Je cherchais juste une belle façon de le faire (l'embarquer dans la classe mais accessible depuis l'extérieur).
Je vais donc mettre un petit exemple qui montre comment PHP peut être magnifique quand il est utilisé avec tacte.
Tout d'abord, on va commencer par accepter une seule connexion. Notre serveur :
<?php
require_once 'Core.php';
import('Socket.Connection.Server');
import('Socket.Internet.Ipv4');
$ip = new Hoa_Socket_Internet_Ipv4('127.0.0.1', 1234, 'tcp');
$sv = new Hoa_Socket_Connection_Server($ip);
$sv->connect();
var_dump($sv->read(21));
var_dump($sv->writeAll('ok'));Et on attaque notre client :
<?php
require_once 'Core.php';
import('Socket.Connection.Client');
import('Socket.Internet.Ipv4');
$ip = new Hoa_Socket_Internet_Ipv4('127.0.0.1', 1234, 'tcp');
$cl = new Hoa_Socket_Connection_Client($ip);
$cl->connect();
var_dump($cl->writeAll('message from client' . "\r\n"));
var_dump($cl->read(2));On ouvre maintenant deux terminaux, on lance le serveur, puis le client, et tout fonctionne. On aura ceci :
Terminal du serveur :
string(21) "message from client
"
int(2)
Terminal du client :
int(21)
string(2) "ok" Yepee
. Sauf que si on veut plusieurs connexions, ça devient compliqué. Pas de fork dans PHP, pas de thread non plus, la solution est donc dans le select().
On reprend légèrement notre code côté client, on ajoute :
sleep(3600); à la fin, pour éviter un bug actuel (connu, facile, logique et en cours de correction, on est sur le trunk n'est-ce pas
).
On retouche alors notre serveur :
$ip = …;
$sv = …;
$sv->connectAndWait(); // attention, connect() est différent de connectAndWait() !
while(true)
foreach($sv->select() as $node) {
var_dump($sv->read(21));
var_dump($sv->writeAll('ok'));
}On relance notre serveur mais on lance deux clients. On voit que le code à l'intérieur du foreach() est exécuté pour chaque client.
Qu'est-ce qu'on doit comprendre ?
Quand on fait un select(), on va prendre toutes les connexions en demande entrante ok. On les place dans un itérateur et ça roule. Sauf que l'itérateur agît un peu de manière amusante.
Déjà, on voit que l'on travaille toujours sur $sv ? Bah oui, le flux manipulé change en fonction de la connexion sélectionnées ! Déjà ça, c'est assez sympa. Surtout qu'on ne change pas d'objet, c'est appréciable. Je ne vous raconte pas comme c'est beau
.
Ensuite, l'itérateur nous propose une valeur $node. Qu'est-ce ? Un objet qui contient des informations sur la connexion. Par défaut, un ID seulement. Mais vous pouvez ajouter pas mal d'autres informations ; dans le cas des WebSockets par exemple, on peut ajouter : première échange, handshake passé ou pas etc. Ça associe une structure de données à une connexion en bref.
Les choses remarquables sont : le changement de flux alors qu'on ne change pas d'objet et tout reste cohérent (on remarquera la flexibilité de Hoa_Stream et son interface, ainsi que la puissance d'abstraction de la POO), l'association de node à une connexion et l'itération tardive des connexions sélectionnées (on sélectionne, on temporise, on itère).
Voilà. Je trouve que c'est une manière très éléguante de gérer les select(). Et vous ?
PS : je travaille sur les sockets pour pouvoir tester XYL dans un cadre asynchrone ; je tiens à vous rassurer
.