-- $Id: echo.ghc,v 1.2 2001/05/01 20:19:52 doug Exp $ -- http://www.bagley.org/~doug/shootout/ -- Haskell echo/client server -- written by Brian Gregor -- compile with: -- ghc -O -o echo -package net -package concurrent -package lang echo.hs module Main where import SocketPrim import Concurrent import System (getArgs,exitFailure) import Exception(finally) import MVar server_sock = do s <- socket AF_INET Stream 6 setSocketOption s ReuseAddr 1 bindSocket s (SockAddrInet (mkPortNumber portnum) iNADDR_ANY) listen s 2 return s echo_server s = do (s', clientAddr) <- accept s proc <- read_data s' 0 putStrLn ("server processed "++(show proc)++" bytes") sClose s' where read_data sock totalbytes = do (str,i) <- readSocket sock 19 if (i >= 19) then (do writ <- writeSocket sock str read_data sock $! (totalbytes+(length $! str))) else (return totalbytes) local = "127.0.0.1" message = "Hello there sailor\n" portnum = 7001 client_sock = do s <- socket AF_INET Stream 6 ia <- inet_addr local connect s (SockAddrInet (mkPortNumber portnum) ia) return s echo_client n = do s <- client_sock drop <- server_echo s n sClose s where server_echo sock n | n > 0 =(do writeSocket sock message (str,i) <- readSocket sock 19 if (str /= message) then (do exitFailure) else server_echo sock (n-1)) | otherwise = (return []) main = do ~[n] <- getArgs -- server & client semaphores --get the server socket ssock <- server_sock -- fork off the server s <- myForkIO (echo_server ssock) -- fork off the client c <- myForkIO (echo_client (read n::Int)) -- let 'em run until they've signaled they're done join s ; join c -- these are used to make the main thread wait until -- the child threads have exited myForkIO :: IO () -> IO (MVar ()) myForkIO io = do mvar <- newEmptyMVar forkIO (io `finally` putMVar mvar ()) return mvar join :: MVar () -> IO () join mvar = readMVar mvar