Created
July 12, 2016 19:28
-
-
Save Tehnix/b246f1a73d30107ea59659dba09f9ec3 to your computer and use it in GitHub Desktop.
Example of networking with a server and client (as bonus it also uses forkIO for threading and MVar's for thread communication).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main where | |
import Control.Monad (unless) | |
import Network.Socket hiding (recv) | |
import qualified Data.ByteString as S | |
import qualified Data.ByteString.Char8 as C | |
import Network.Socket.ByteString (recv, sendAll) | |
import Control.Concurrent (forkIO) | |
import Control.Concurrent.MVar (takeMVar, putMVar, newEmptyMVar, MVar) | |
portNumber :: Integer | |
portNumber = 3000 | |
main :: IO () | |
main = do | |
-- Control when to start the client, and when to shut down the program | |
serverHasStarted <- newEmptyMVar | |
serverHasClosed <- newEmptyMVar | |
-- Run the server in a thread | |
putStrLn $ ">> Running server in a thread on port " ++ show portNumber ++ "..." | |
forkIO $ runTestServer serverHasStarted serverHasClosed | |
-- Start the client when the server has started, by waiting for | |
-- the MVar `serverHasStarted` | |
takeMVar serverHasStarted | |
putStrLn $ ">> The server has started!" | |
putStrLn $ ">> Starting client on port " ++ show portNumber ++ "..." | |
runTestClient | |
-- Make sure the server has closed properly by waiting for the MVar | |
-- `serverHasClosed` | |
takeMVar serverHasClosed | |
runTestServer :: MVar () -> MVar () -> IO () | |
runTestServer hasStarted hasClosed = do | |
withSocketsDo $ | |
do addrinfos <- getAddrInfo | |
(Just (defaultHints {addrFlags = [AI_PASSIVE]})) | |
Nothing (Just (show portNumber)) | |
let serveraddr = head addrinfos | |
sock <- socket (addrFamily serveraddr) Stream defaultProtocol | |
bindSocket sock (addrAddress serveraddr) | |
listen sock 1 | |
putMVar hasStarted () | |
(conn, _) <- accept sock | |
talk conn | |
sClose conn | |
sClose sock | |
putMVar hasClosed () | |
where | |
talk :: Socket -> IO () | |
talk conn = | |
do msg <- recv conn 1024 | |
unless (S.null msg) $ sendAll conn msg >> talk conn | |
runTestClient :: IO () | |
runTestClient = do | |
withSocketsDo $ | |
do addrinfos <- getAddrInfo Nothing (Just "") (Just (show portNumber)) | |
let serveraddr = head addrinfos | |
sock <- socket (addrFamily serveraddr) Stream defaultProtocol | |
connect sock (addrAddress serveraddr) | |
sendAll sock $ C.pack "Hello, world!" | |
msg <- recv sock 1024 | |
sClose sock | |
putStr "Received " | |
C.putStrLn msg |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment