(* Compilieren mit: ocamlc -o serverml unix.cma server.ml oder ocamlopt-o serverml unix.cmxa echoserver.ml Starten mit : ./serverml *) open Unix open Printf open String let err_unknown_cmd = "ERROR unknown command\n" exception WriteFailure let readline sd = let c = " " in let rec loop res = if (read sd c 0 1) = 1 then if c = "\n" then res^c else loop (res^c) else raise End_of_file in loop "" let write_safe sd s = let len = String.length s in if (write sd s 0 len) < len then raise WriteFailure let split_at_space s = if (contains s ' ') then let space = index s ' ' in (sub s 0 space, sub s space (length s - space)) else (s,"") let rec ltrim aStr = match aStr with "" -> "" | (_) -> if (aStr.[0] = ' ') then ltrim (sub aStr 1 (length aStr -1)) else aStr let calculate args op = match (split_at_space (ltrim args)) with (s, t) -> string_of_int (op (int_of_string (ltrim s)) (int_of_string (ltrim t))) let chop aStr = if ( (aStr.[length aStr -2] = '\r') && (aStr.[length aStr -1] = '\n')) then ( sub aStr 0 (length aStr -2)) else if (aStr.[length aStr -1] = '\n') then sub aStr 0 (length aStr -1) else aStr let get_ip sock_addr = match sock_addr with ADDR_INET (inet_addr, port) -> string_of_inet_addr inet_addr | _ -> failwith "get_ip" let main = let sd = socket PF_INET SOCK_STREAM 0 in bind sd (ADDR_INET(inet_addr_any, 9000)); listen sd 5; let rec server_loop () = let (csd, client_addr) = accept sd in let rec client_loop () = match split_at_space(chop(readline csd)) with ("INFO", _) -> begin write_safe csd ("YOURIP "^(get_ip client_addr) ^ "\n"); client_loop () end | ("QUIT", _) -> begin close csd; server_loop () end | ("ADD", args) -> begin write_safe csd ((calculate args ( + )) ^ "\n"); client_loop () end | ("MUL", args) -> begin write_safe csd ((calculate args ( * )) ^ "\n"); client_loop () end | _ -> begin write_safe csd err_unknown_cmd; client_loop () end in client_loop () in handle_unix_error server_loop ()