CyberRail, c'est le nom de mon future simulateur/contrôleur de réseau férroviaire.

Hier soir, en panne d'inspiration pour occuper ma soirée[1], je me suis mis à écrire la couche communication de ce projet. Il s'agissait de faire une couche réseau simple et qui fonctionne par évenement.

Actuellement, quand vous voulez faire de la communication réseau de manière asynchrone, on vous parle tout de suite de thread et autres concepts de ce genre. La parrallélisation des tâches, c'est bien gentil, mais ça apporte une certaine complexité qui finalement masque les intérêts de cette technique. L'autre moyen utilisé est l'appel système poll(). Sa programmation est assez complexe, et à la fin, en général, on s'emmele les pinceaux plus qu'autre chose.

J'ai décidé d'écrire CyerRail en python, parce que c'est ma marrote du moment, parce que c'est simple à écrire, parce que c'est moins lourd que Java et plus lisible que le C. La bibliothèque python fournit tous les appels systèmes de la libc, et notamment l'api BSD socket, ainsi que l'api select (qui contient l'appel système poll()). tout l'interet de le faire en python est que la gestion d'erreur est triviale : il n'y a pas de code de retour, les erreurs sont gerées par des exceptions, il n'y a pas de taille de buffer, etc, etc...

Cette simplification de l'api, ainsi que la notion d'objet, permet de se concentrer sur le fonctionnement réel du système, et donc de ne pas perdre de vue le but vers lequel on veut tendre. J'ai donc réussi hier soir à réalisé une petite bibliothèque multi-connexions ne fonctionnant qu'avec un seul thread (cela dit, le reste du programme devra peut-être tourner avec un autre thread en cas d'interface graphique ou autre...) quelque soit le nombre de connexion à gérer.

La bibliothèque communique avec le reste du programme par un système d'écouteurs : en cas de nouvelle connexion, des évenements sont envoyés à qui veut bien l'entendre et permettent un éventuel traitement par le reste du programme. J'ai également intégré deux niveaux d'évenements : ceux bas niveau (poll retourne, des octets sont envoyés ou reçu, une connexion s'est créée ou a été fermée), et ceux de haut niveau (liaison établie, une requète a été reçue, etc...).

Le seul problème est que la portabilité Windows n'est pas assurée. En effet, le problème est le suivant. Un appel externe à la bibliothèque demande l'envoie de données. Ces données sont ajoutées dans une file, et devraient être envoyées au porchain tour de boucle de poll. Malheureusement, poll n'a pas été avertit qu'il devait vérifier si des données peuvent être envoyées sur la socket. Résultat, poll ne peut pas prendre en compte les nouvelles données, et reste bloqué jusqu'à ce qu'un autre évenement vienne le réveiller. Comme cet évennement est completement indépendant des données à envoyer, on ne peut pas garantir que les données partiront, et encore moins qu'elles partiront tout de suite. L'astuce est donc de créer un tube (un pipe), et de mettre la sortie dans la liste des descripteurs que poll doit surveiller. Lorsque l'on veut envoyer des données, il suffira dont de mettre un caractère dans l'entrée du tube, ce qui aura pour effet de réveiller poll. On pourra donc rafraichir sa liste de descripteur, et donc lui permettre de surveiller la socket en écriture, et éventuellement écrire les données si cette socket est prete.

Le problème est que sous windows, l'appel poll est implémenté dans winsock, ce qui a pour effet qu'elle ne peut pas prendre en compte des descripteurs autres que des sockets, et donc pas notre malheureux tube qui permet de réveiller poll quand des données doivent être envoyées.

On pourra dire que je réinvente une ènième fois la roue, mais tout ce fatra me permettra de me concentrer sur les couches de plus haut niveau sans avoir à gerer le reste, et surtout, sans avoir a gérer les complexités d'une bibliothèque plus imposante, qui fait tout toute seule et qui, au final, ne possède pas la petite propriété qui fait que ça marche comme il faut.

Notes

[1] On n'a plus ni télévision ni téléphone (et donc pas d'ADSL) depuis les violences de samedi soir (mise à feu des encombrants et du local poubelles)