(* -*- mode: sml -*-
* $Id: echo.smlnj,v 1.1 2001/07/10 00:47:14 doug Exp $
* http://www.bagley.org/~doug/shootout/
* from Daniel Wang
*)
structure Test : sig
val main : (string * string list) -> OS.Process.status
end =
struct
exception Error of string
val data = "Hello there sailor\n"
fun mkSocks () = let
val server = INetSock.TCP.socket()
val client = INetSock.TCP.socket()
val _ = Socket.bind(server,INetSock.any 0)
val saddr = INetSock.fromAddr(Socket.Ctl.getSockName server)
val _ = Socket.listen(server,2)
val _ = Socket.connect(client,INetSock.toAddr saddr)
val _ = INetSock.TCP.setNODELAY(server,true)
val _ = INetSock.TCP.setNODELAY(client,true)
in {client=client,server=server}
end
fun readString (s,n) = let
fun loop(0) = []
| loop(n) = let
val data = Byte.bytesToString(Socket.recvVec(s,n))
val len = String.size data
in if len = 0 then []
else (data::(loop(n - len)))
end
in String.concat (loop n)
end
fun writeString (out,str) =
Socket.sendVec(out,{buf=Byte.stringToBytes str,i=0,sz=NONE})
fun closeSock s =
(Socket.shutdown(s,Socket.NO_RECVS_OR_SENDS);
Socket.close s)
fun main (_,args) = let
val num =
case args of
nil => 1
| n::_ => valOf (Int.fromString n)
val {client=client_sock,server=server_sock} = mkSocks()
fun server () = let
val (sock,_) = Socket.accept(server_sock)
fun s b =
case readString(sock,19) of
"" => (Posix.Process.wait ();
TextIO.output(TextIO.stdOut,
concat ["server processed ",
Int.toString b,
" bytes\n"]);
TextIO.flushOut(TextIO.stdOut))
| i =>(writeString(sock,i);
s (b + 19))
in s 0
end
fun client () = let
fun c 0 = closeSock(client_sock)
| c n = let
val _ = writeString(client_sock,data);
val reply = readString(client_sock,19)
in if reply = data then c(n - 1)
else raise Error "Didn't receive the same data"
end
in c num
end
in
case Posix.Process.fork () of
SOME pid => server ()
| NONE => client ();
OS.Process.success
end
end
val _ = SMLofNJ.exportFn("echo",Test.main);