如何关闭`runTCPServer`?

时间:2016-06-19 14:46:23

标签: haskell network-conduit

我正在编写一个runTCPServer来自conduit-extra的套接字服务器(以前称为network-conduit)。我的目标是使用这个服务器与我的编辑器进行交互---从编辑器激活服务器(最有可能只是通过调用外部命令),使用它,并在工作完成后终止服务器。

为简单起见,我从一个简单的echo服务器开始,让我们说我想在连接关闭时关闭整个过程。

所以我试过了:

{-# LANGUAGE OverloadedStrings #-}
module Main where
import Data.Conduit
import Data.Conduit.Network
import Data.ByteString (ByteString)
import Control.Monad.IO.Class (liftIO)
import System.Exit (exitSuccess)
import Control.Exception

defaultPort :: Int
defaultPort = 4567
main :: IO ()
main = runTCPServer (serverSettings defaultPort "*") $ \ appData ->
        appSource appData $$ conduit =$= appSink appData

conduit :: ConduitM ByteString ByteString IO ()
conduit = do
    msg <- await
    case msg of
         Nothing -> liftIO $ do
             putStrLn "Nothing left"
             exitSuccess
             -- I'd like the server to shut down here
         (Just s) -> do
             yield s
             conduit

但这不起作用 - 该计划继续接受新的联系。如果我没有弄错的话,这是因为线程正在听取我们用exitSuccess处理退出的连接,但整个过程都没有。所以这完全可以理解,但我还没有找到退出整个过程的方法。

如何终止runTCPServer运行的服务器? runTCPServer是应该永远服务的东西吗?

1 个答案:

答案 0 :(得分:2)

以下是评论中描述的想法的简单实现:

main = do
     mv <- newEmptyMVar
     tid <- forkTCPServer (serverSettings defaultPort "*") $ \ appData ->
        appSource appData $$ conduit mv =$= appSink appData
     () <- takeMVar mv -- < -- wait for done signal
     return ()

conduit :: MVar () -> ConduitM ByteString ByteString IO ()
conduit mv = do
    msg <- await
    case msg of
         Nothing -> liftIO $ do
             putStrLn "Nothing left"
             putMVar mv () -- < -- signal that we're done
         (Just s) -> do
             yield s
             conduit mv