3import Network.Transport
4import Network.Transport.TCP
9import Network.Socket (HostName, ServiceName)
10import System.Environment
12import qualified Data.ByteString.Char8 as BS
18-- | This example demonstrates how a master can be connected to slaves using
19-- the transport layer. After compiling, the following will initialize a new
20-- master that waits for two clients to connect on the local machine:
22-- ./DemoTCP 127.0.0.1 8080 sourceAddrFile 2
24-- Following this, two slaves should be created that will connect to the master:
26-- ./DemoTCP 127.0.0.1 8081 sourceAddrFile
27-- ./DemoTCP 127.0.0.1 8082 sourceAddrFile
29-- Once the connection is established, the slaves will provide the master
30-- with their SourceAddr. The master then decodes this, and sends a message
31-- back. After processing this message, the slaves respond to the master,
32-- which then outputs some data.
38 -- The master only provides the host, service, and slaves to expect.
39 [host, service, sourceAddrFilePath, number] -> do
40 let numSlaves = read number
41 transport <- mkTransport $ TCPConfig defaultHints host service
42 (clientSourceEnds, masterTargetEnd) <- demoMaster transport sourceAddrFilePath numSlaves
44 (\clientSourceEnd clientId ->
45 send clientSourceEnd [BS.pack . show $ clientId])
46 clientSourceEnds [0 .. numSlaves-1]
47 replicateM_ numSlaves $ do
48 [clientMessage] <- receive masterTargetEnd
51 closeTargetEnd masterTargetEnd
52 putStrLn "master: close connections"
55 -- Each slave provides its own host and service, as well as details of
56 -- the master it wishes to connect to.
57 [host, service, sourceAddrFilePath] -> do
58 transport <- mkTransport $ TCPConfig defaultHints host service
59 (masterSourceEnd, slaveTargetEnd) <- demoSlave transport sourceAddrFilePath
60 [clientId] <- receive slaveTargetEnd
61 putStrLn $ "slave: received clientId: " ++ show clientId
62 let message = "Connected to slave: " ++ (BS.unpack clientId)
64 send masterSourceEnd [BS.pack message]
65 putStrLn "slave: sent message to master"
67 closeSourceEnd masterSourceEnd
68 putStrLn "slave: close connection"
70 _ -> error "Unexpected arguments"
72demoMaster :: Transport -- ^ Transport
73 -> FilePath -- ^ File to write SourceAddr
74 -> Int -- ^ Number of slaves to expect
75 -> IO ([SourceEnd], TargetEnd)
76demoMaster transport sourceAddrFilePath numSlaves = do
77 -- Establish an initial transport
78 (sourceAddr, targetEnd) <- newConnection transport
80 -- Write a file containing the sourceAddr
81 putStrLn $ "master: writing sourceAddr file:" ++ (show . serialize $ sourceAddr)
82 BS.writeFile sourceAddrFilePath $ serialize sourceAddr
84 -- Deserialize each of the sourceEnds received by the slaves
85 sourceEnds <- replicateM numSlaves $ do
86 [bytes] <- receive targetEnd
87 putStrLn "master: received connection."
88 case deserialize transport bytes of
89 Nothing -> fail "Garbage message from slave!"
90 Just sourceAddr -> connect sourceAddr
91 return (sourceEnds, targetEnd)
93demoSlave :: Transport -- ^ Transport
94 -> FilePath -- ^ File to read SourceAddr
95 -> IO (SourceEnd, TargetEnd)
96demoSlave transport masterSourceAddrFilePath = do
97 -- Create a new connection on the transport
98 (sourceAddr, targetEnd) <- newConnection transport
100 -- Establish connection with the master
101 bytes <- BS.readFile masterSourceAddrFilePath
102 case deserialize transport bytes of
103 Just masterSourceAddr -> do
104 putStrLn $ "slave: connecting to sourceAddr: " ++ (show . serialize $ masterSourceAddr)
105 masterSourceEnd <- connect masterSourceAddr
107 -- Source the serialized address of this slave
108 send masterSourceEnd [serialize sourceAddr]
109 putStrLn "slave: sent sourceAddr"
110 return (masterSourceEnd, targetEnd)
112 Nothing -> error "slave: Unable to deserialize master SourceAddr!"
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list