{-# LANGUAGE OverloadedStrings #-}
-- A simple example of an epoll based http server in Haskell.
--
-- Uses two libraries:
-- * network-bytestring, bytestring-based socket IO.
-- - cabal install network-bytestring:
--
-- * haskell-event, epoll-based scalable IO events
-- - git clone git://github.com/tibbe/event.git
-- - autoreconf ; then cabal install
import Network hiding (accept)
import Network.Socket (fdSocket, accept)
import Network.Socket.ByteString
import Data.ByteString.Char8
import System.Event
import System.Posix
import System.Posix.IO
main = withSocketsDo $ do
sock <- listenOn $ PortNumber 5002
let fd = fromIntegral (fdSocket sock)
mgr <- new
registerFd mgr (client sock) fd evtRead
loop mgr
client sock _ _ = do
(c,_) <- accept sock
sendAll c msg
sClose c
msg = "HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\nPong!\r\n"
btnz@vmubuntuserver:~/work/code/echo-server-event-model$ cat Main.hs
module Main where
import Network.Socket
import Network.Socket.ByteString (recv, sendAll)
import GHC.Event as Event
import qualified Control.Exception as E (bracket)
import Data.ByteString.Internal (packChars)
hints = defaultHints {addrFlags = [AI_PASSIVE], addrSocketType = Stream}
msg = "HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\nPong!\r\n"
main :: IO ()
main = do
putStrLn "Hello, Haskell!"
addr <- head <$> getAddrInfo (Just hints) Nothing (Just "3000")
E.bracket (sock addr) close eventServer
return ()
where
sock addr = do
s <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
setSocketOption s ReuseAddr 1
withFdSocket s setCloseOnExecIfNeeded
bind s $ addrAddress addr
listen s 1024
return s
eventServer s = do
fd <- withFdSocket s (\ci -> return (fromIntegral ci))
mgr <- Event.new
Event.registerFd mgr (service s) fd Event.evtRead Event.OneShot
-- loop mgr
service :: Socket -> FdKey -> Event -> IO ()
service s _ _ = do
(c, _) <- accept s
sendAll c $ packChars msg
close c
when I run cabal run the program exit directly.