Ich schreibe einen Socket-Server mit runTCPServer
von conduit-extra (früher bekannt als network-conduit). Mein Ziel ist es, mit meinem Editor über diesen Server zu interagieren --- den Server vom Editor aus zu aktivieren (höchstwahrscheinlich nur durch Aufruf eines externen Befehls), ihn zu benutzen und den Server zu beenden, wenn die Arbeit erledigt ist.Wie kann ich "runTCPServer" herunterfahren?
Der Einfachheit halber beginne ich mit einem einfachen Echo-Server, und sagen wir, ich möchte den gesamten Prozess herunterfahren, wenn die Verbindung geschlossen wird.
Also habe ich versucht:
{-# 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
Aber das funktioniert nicht - das Programm weiterhin neue Verbindungen zu akzeptieren. Wenn ich mich nicht irre, liegt das daran, dass der Thread, der die Verbindung abhört, mit der wir es zu tun haben, mit exitSuccess
ausgeht, aber der gesamte Prozess nicht. Das ist völlig verständlich, aber ich war nicht in der Lage, einen Weg zu finden, den gesamten Prozess zu beenden.
Wie kann ich einen Server beenden, der von runTCPServer
ausgeführt wird? Ist runTCPServer
etwas, das für immer dienen soll?
'exit' aus dem Haupt-Thread aufgerufen werden muss (ich bin nicht sicher, warum, aber das ist die Anforderung). Sie können "runTCPServer" immer in einem separaten 'forkIO'd-Thread ausführen und den Hauptthread auf einige' MVar' warten lassen, die der Worker-Thread festlegt, wenn eine Beendigungsnachricht eintrifft. –
Und ja, 'runTCPServer' soll für immer laufen, siehe [Quelle] (https://hackage.haskell.org/package/streaming-commons-0.1.15.5/docs/src/Data-Streaming-Network.html# runTCPServerWithHandle). –
@ n.m. Das scheint die genaue Antwort zu sein (besonders 'forkIO' und' MVar'), nach der ich gesucht habe. Würden Sie ein einfaches Beispiel hinzufügen (wenn es Ihnen nichts ausmacht) und das als Antwort posten? – Yosh