Un serveur très select..


h1 5/21/2006 10:41:00 PM

Le retour du post geekesque !

Il y a quelques années il me semble avoir lu dans Linux Magazine un article expliquant comment programmer en C un serveur léger et rapide sans threads. Jusque récemment, liquidsoap (qui offre quelques interactions via une interface telnet) utilisait un serveur à base de threads: un thread écoute sur le serveur et accepte les clients, lance un nouveau thread par client pour traiter ses requêtes. C'est mauvais: au bout de 30 clients on a 30 threads, ce qui plombe l'application; et en plus les clients ne sont pas vite servis, la création de leur thread étant coûteuse. J'ai enfin changé ça, en utilisant l'appel système select pour attendre un ensemble d'évenements sur des sockets. C'est ultra simple et ça marche impeccable.

L'article de Linux Mag aurait pu être écrit en Caml au lieu de C: au lieu de fournir un exemple de serveur, on peut en programmation fonctionnelle implémenter un serveur générique se chargeant d'ordonnancer des pseudo-threads représentés par des fonctions. Je vous le livre ici. Accessoirement, j'ai cherché à trouver ce genre de code tout prêt sur le net avant de l'écrire. Peut être que j'épargnerai du boulot à quelqun.

type task =
| Read of (Unix.file_descr * (unit -> unit))
| Write of (Unix.file_descr * (unit -> unit))
| Special of (Unix.file_descr * (unit -> unit))

let scheduler init =
let read = ref [] in
let write = ref [] in
let special = ref [] in
let add set a = set := a :: !set in
let add = function
| Read (s,f) -> add read (s,f)
| Write (s,f) -> add write (s,f)
| Special (s,f) -> add special (s,f)
in
let process set sockets =
(* Events are triggered on a list of sockets.
* Execute the corresponding handlers, and remove them from the set. *)
let f = List.map (fun s -> List.assoc s !set) sockets in
set := List.filter (fun (s,_) -> not (List.mem s sockets)) !set ;
List.iter (fun f -> f ()) f
in
init add ;
while true do
let r,w,x =
Unix.select
(List.map fst !read) (List.map fst !write) (List.map fst !special)
(-1.)
in
process read r ;
process write w ;
process special x
done


Pour les curieux le code complet est sur le SVN de Savonet, avec enregistrement et traitement des clients..

0 commentaires:

Un commentaire ?

< Accueil