summaryrefslogtreecommitdiff
path: root/net/server.hs
diff options
context:
space:
mode:
authorAndrew Guschin <saintruler@gmail.com>2020-11-26 13:55:55 +0400
committerAndrew Guschin <saintruler@gmail.com>2020-11-26 13:55:55 +0400
commit446602fe336ad1c2a23e3d50d7cd1d1356fcc9de (patch)
tree74b8a1ca93c17d22f7876f6aba80ee10c3851d3b /net/server.hs
Initial commit
Diffstat (limited to 'net/server.hs')
-rw-r--r--net/server.hs42
1 files changed, 42 insertions, 0 deletions
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)
+