(* * $Id: echo.ocaml,v 1.8 2001/05/13 17:13:06 doug Exp $ * http://www.bagley.org/~doug/shootout/ * with help from Markus Mottl *) open Unix let data = "Hello there sailor\n" let rec sock_write sock buf offset len = if len > 0 then begin let nwritten = write sock buf offset len in sock_write sock buf (offset + nwritten) (len - nwritten) end let sock_readline buf sock = let offset = ref (read sock buf 0 64) in while String.get buf (!offset - 1) <> '\n' do offset := !offset + (read sock buf !offset 64) done; !offset let rec buf_ok buf n = n <= 0 || buf.[n] = data.[n] && buf_ok buf (n - 1) let echo_client n port = let sock = socket PF_INET SOCK_STREAM 0 in connect sock (ADDR_INET (inet_addr_of_string "127.0.0.1", port)); let len = String.length data and buf = String.create 64 in for i = 1 to n do sock_write sock data 0 len; let ans_len = sock_readline buf sock in if ans_len <> len || not (buf_ok buf (len - 1)) then begin prerr_string "client got bad data: "; prerr_endline (String.sub buf 0 ans_len); exit 1 end done; close sock let ssock = let ssock = socket PF_INET SOCK_STREAM 0 and addr = inet_addr_of_string "127.0.0.1" in bind ssock (ADDR_INET (addr, 0)); setsockopt ssock SO_REUSEADDR true; listen ssock 2; ssock let get_port sock = match getsockname sock with | ADDR_INET (_, port) -> port | ADDR_UNIX _ -> raise (Failure "getsockname") let echo_server n = let port = get_port ssock and pid = fork() in if pid <> 0 then begin let csock, addr = accept ssock and buf = String.create 64 and len = ref 0 and nread = ref 1 in while !nread > 0 do nread := read csock buf 0 64; sock_write csock buf 0 !nread; len := !len + !nread done; ignore (wait ()); Printf.printf "server processed %d bytes\n" !len end else echo_client n port let _ = let n = try int_of_string Sys.argv.(1) with Invalid_argument _ -> 1 in echo_server n