/
DoublingServer5.hs
75 lines (63 loc) · 2.53 KB
/
DoublingServer5.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
-- Based on the TrivialServer-example from Marlow, Parallel and Concurrent
-- Programming in Haskell
{-# LANGUAGE StandaloneDeriving #-}
import System.IO
import Network
import Text.Printf
import Control.Monad
import Control.Concurrent
import Debug.Hoed(observe,Observable(..),runO,send,observe',Identifier(..))
import System.IO.Unsafe
import Data.List
twotimes :: Int -> Integer -> Integer
twotimes d j = (fst $ observe' "twotimes" (DependsJustOn d)
( \i -> {-# SCC "twotimes" #-}
2 + i -- bug: should be 2 * i
)) j
double :: String -> String
double s' = let (res,d) = observe' "double" UnknownId
(\s -> {-# SCC "double" #-} show (twotimes d (read s :: Integer)))
in res s'
loop h = do
line <- hGetLine h
if line == "end"
then do hPutStrLn h ("Thank you for using the Haskell doubling service.")
putStrLn $ "server: Terminated client " ++ show h
else do hPutStrLn h (double line)
loop h
talk :: Handle -> IO ()
talk h = do
hSetBuffering h LineBuffering
i <- myThreadId
hPutStrLn h $ "Welcome on thread " ++ show i
loop h
port :: Int
port = 44444
server :: Int -> Socket -> IO ()
server = observe "server" (\x sock -> {-# SCC "server" #-} server' x sock)
where server' 0 _ = putStrLn "server: Shutting down."
server' x sock = do
(handle, host, port) <- accept sock
printf "server: Accepted connection from %s: %s\n" host (show port)
forkFinally (talk handle) (\_ -> hClose handle)
server (x-1) sock
client :: Int -> IO ()
client x = do
h <- connectTo "localhost" (PortNumber (fromIntegral port))
hSetBuffering h LineBuffering
let pr s = putStrLn $ "client-" ++ show x ++ ": " ++ s
s <- hGetLine h; pr s -- Get and print the welcome message
hPutStrLn h (show x) -- Send x for doubling to the server
s <- hGetLine h; pr s -- Get and print response from server
hPutStrLn h "end" -- Send goodbye message
s <- hGetLine h; pr s -- Get and print response from server
main :: IO ()
main = runO $ withSocketsDo $ do
sock <- listenOn (PortNumber (fromIntegral port))
printf "server: Listening on port %d.\n" port
forkIO (server 2 sock) -- Start server in own thread.
client 2 -- Connect with two clients from this thread to the server.
client 3
threadDelay 1000 -- Give server-thread some time to terminate.
instance Observable Handle where observer h = send (show h) (return h)
instance Observable Socket where observer s = send "socket" (return s)