diff options
| author | Andrew Guschin <saintruler@gmail.com> | 2020-11-26 13:55:55 +0400 |
|---|---|---|
| committer | Andrew Guschin <saintruler@gmail.com> | 2020-11-26 13:55:55 +0400 |
| commit | 446602fe336ad1c2a23e3d50d7cd1d1356fcc9de (patch) | |
| tree | 74b8a1ca93c17d22f7876f6aba80ee10c3851d3b /net | |
Initial commit
Diffstat (limited to 'net')
| -rw-r--r-- | net/client.hs | 30 | ||||
| -rw-r--r-- | net/server.hs | 42 |
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) + |