summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/client.hs30
-rw-r--r--net/server.hs42
2 files changed, 72 insertions, 0 deletions
diff --git a/net/client.hs b/net/client.hs
new file mode 100644
index 0000000..863df6e
--- /dev/null
+++ b/net/client.hs
@@ -0,0 +1,30 @@
+{-# LANGUAGE OverloadedStrings #-}
+-- Echo client program
+module Main (main) where
+
+import qualified Control.Exception as E
+import qualified Data.ByteString.Char8 as C
+import Network.Socket
+import Network.Socket.ByteString (recv, sendAll)
+
+main :: IO ()
+main = runTCPClient "127.0.0.1" "3000" $ \s -> do
+ sendAll s "Hello, world!"
+ msg <- recv s 1024
+ putStr "Received: "
+ C.putStrLn msg
+
+-- from the "network-run" package.
+runTCPClient :: HostName -> ServiceName -> (Socket -> IO a) -> IO a
+runTCPClient host port client = withSocketsDo $ do
+ addr <- resolve
+ E.bracket (open addr) close client
+ where
+ resolve = do
+ let hints = defaultHints { addrSocketType = Stream }
+ head <$> getAddrInfo (Just hints) (Just host) (Just port)
+ open addr = do
+ sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
+ connect sock $ addrAddress addr
+ return sock
+
diff --git a/net/server.hs b/net/server.hs
new file mode 100644
index 0000000..a9bec82
--- /dev/null
+++ b/net/server.hs
@@ -0,0 +1,42 @@
+-- Echo server program
+module Main (main) where
+
+import Control.Concurrent (forkFinally)
+import qualified Control.Exception as E
+import Control.Monad (unless, forever, void)
+import qualified Data.ByteString as S
+import Network.Socket
+import Network.Socket.ByteString (recv, sendAll)
+
+main :: IO ()
+main = runTCPServer Nothing "3000" talk
+ where
+ talk s = do
+ msg <- recv s 1024
+ unless (S.null msg) $ do
+ sendAll s msg
+ talk s
+
+-- from the "network-run" package.
+runTCPServer :: Maybe HostName -> ServiceName -> (Socket -> IO a) -> IO a
+runTCPServer mhost port server = withSocketsDo $ do
+ addr <- resolve
+ E.bracket (open addr) close loop
+ where
+ resolve = do
+ let hints = defaultHints {
+ addrFlags = [AI_PASSIVE]
+ , addrSocketType = Stream
+ }
+ head <$> getAddrInfo (Just hints) mhost (Just port)
+ open addr = do
+ sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
+ setSocketOption sock ReuseAddr 1
+ withFdSocket sock $ setCloseOnExecIfNeeded
+ bind sock $ addrAddress addr
+ listen sock 1024
+ return sock
+ loop sock = forever $ do
+ (conn, _peer) <- accept sock
+ void $ forkFinally (server conn) (const $ gracefulClose conn 5000)
+