(* ligne de compilation ocaml 3.02 ocamlc -o serv.exe -thread -custom unix.cma threads.cma server.ml -cclib -lthreads -cclib -lunix *) (* 4 classes pour un serveur generique *) (* class virtual server : int -> int -> object method start : unit -> unit method virtual treat : Unix.file_descr -> Unix.sockaddr -> unit val nb_pending : int val port_num : int val sock : Unix.file_descr end *) class virtual server port n = object (s) val port_num = port val nb_pending = n val sock = ThreadUnix.socket Unix.PF_INET Unix.SOCK_STREAM 0 method start () = let host = Unix.gethostbyname (Unix.gethostname()) in let h_addr = host.Unix.h_addr_list.(0) in let sock_addr = Unix.ADDR_INET(h_addr, port_num) in Unix.bind sock sock_addr ; Unix.listen sock nb_pending ; while true do let (service_sock, client_sock_addr) = ThreadUnix.accept sock in s#treat service_sock client_sock_addr done method virtual treat : Unix.file_descr -> Unix.sockaddr -> unit end ;; (* val gen_num : unit -> int *) let gen_num = let c = ref 0 in (fun () -> incr c; !c) ;; (* class virtual connexion : Unix.file_descr -> Unix.sockaddr -> bool -> object method virtual run : unit -> unit method set_debug : bool -> unit method start : unit -> Thread.t method stop : unit -> unit val mutable debug : bool val mutable numero : int val s_addr : Unix.sockaddr val s_descr : Unix.file_descr end *) class virtual connexion sd (sa : Unix.sockaddr) b = object (self) val s_descr = sd val s_addr = sa val mutable numero = 0 val mutable debug = b method set_debug b = debug <- b initializer numero <- gen_num(); if debug then ( Printf.printf "TRACE.connexion : objet traitant %d cree\n" numero ; print_newline()) method start () = Thread.create (fun x -> self#run x ; self#stop x) () method stop() = if debug then ( Printf.printf "TRACE.connexion : fin objet traitant %d\n" numero ; print_newline () ); Unix.close s_descr method virtual run : unit -> unit end;; (* exception Fin val my_input_line : Unix.file_descr -> string *) exception Fin ;; let my_input_line fd = let s = " " and r = ref "" in while (ThreadUnix.read fd s 0 1 > 0) && s.[0] <> '\n' do r := !r ^s done ; !r ;; (* class connexion_maj : Unix.file_descr -> Unix.sockaddr -> bool -> object method run : unit -> unit method set_debug : bool -> unit method start : unit -> Thread.t method stop : unit -> unit val mutable debug : bool val mutable numero : int val s_addr : Unix.sockaddr val s_descr : Unix.file_descr end *) class connexion_maj sd sa b = object(self) inherit connexion sd sa b method run () = try while true do let ligne = my_input_line s_descr in if (ligne = "") or (ligne = "\013") then raise Fin ; let result = (String.uppercase ligne)^"\n" in ignore (ThreadUnix.write s_descr result 0 (String.length result)) done with Fin -> () | exn -> print_string (Printexc.to_string exn) ; print_newline() end ;; (* class server_maj : int -> int -> object method start : unit -> unit method treat : Unix.file_descr -> Unix.sockaddr -> unit val nb_pending : int val port_num : int val sock : Unix.file_descr end *) class server_maj port n = object(s) inherit server port n method treat s sa = ignore( (new connexion_maj s sa true)#start()) end;; (* val main : unit -> unit *) let main () = if Array.length Sys.argv < 3 then Printf.printf "usage : server port num\n" else let port = int_of_string(Sys.argv.(1)) and n = int_of_string(Sys.argv.(2)) in (new server_maj port n )#start();; main();;