Create a network service that sits on TCP port 12321, which accepts connections on that port, and which echoes complete lines (using a carriage-return/line-feed sequence as line separator) back to clients. No error handling is required. For the purposes of testing, it is only necessary to support connections from localhost (127.0.0.1 or perhaps ::1). Logging of connection information to standard output is recommended.

The implementation must be able to handle simultaneous connections from multiple clients. A multi-threaded or multi-process solution may be used. Each connection must be able to echo more than a single line.

The implementation must not stop responding to other clients if one client sends a partial line or stops reading responses.

module Main where
import Network (withSocketsDo, accept, listenOn, sClose, PortID(PortNumber))
import Control.Monad (forever)
import System.IO (hGetLine, hPutStrLn, hFlush, hClose)
import System.IO.Error (isEOFError)
import Control.Concurrent (forkIO)
import Control.Exception (bracket)
 
-- For convenience in testing, ensure that the listen socket is closed if the main loop is aborted
withListenOn port body = bracket (listenOn port) sClose body
 
echo (handle, host, port) = catch (forever doOneLine) stop where
  doOneLine = do line <- hGetLine handle
                 print (host, port, init line)
                 hPutStrLn handle line
                 hFlush handle
  stop error = do putStrLn $ "Closed connection from " ++ show (host, port) ++ " due to " ++ show error
                  hClose handle
 
main = withSocketsDo $
  withListenOn (PortNumber 12321) $ \listener ->
    forever $ do
      acc@(_, host, port) <- accept listener
      putStrLn $ "Accepted connection from " ++ show (host, port)
      forkIO (echo acc)