简单的TCP客户端

Dul*_*gon 6 haskell haskell-platform

我正在尝试在Haskell中实现简单的TCP客户端.但它一旦连接就会关闭.我不知道是什么导致它关闭.我怎么能这样做,以便从服务器打印线路stdoutstdin永久地从服务器发送线路直到stdin收到线路":退出"?

import Control.Monad (forever)
import Network (withSocketsDo, PortID(..), connectTo)
import System.IO
import Control.Concurrent (forkFinally)
import Control.Concurrent.Async (race)

main :: IO ()
main = withSocketsDo $ do
  -- connect to my local tcp server
  handle <- connectTo "192.168.137.1" (PortNumber 44444)
  -- should close the connection using handle after everything is done
  _ <- forkFinally (talk handle) (\_ -> hClose handle)
  return ()

talk :: Handle -> IO ()
talk handle = do
    hSetNewlineMode handle universalNewlineMode
    hSetBuffering handle LineBuffering
    -- if either one of them terminates, other one will get terminated
    _ <- race (interactWithServer handle) (interactWithUser handle)
    return ()

interactWithServer :: Handle -> IO ()
interactWithServer handle = forever $ do
  line <- hGetLine handle
  print line          -- print a line that came from server into stdout

interactWithUser :: Handle -> IO ()
interactWithUser handle = do
  line <- getLine
  case line of
    ":quit" -> return ()            -- stop loop if user input is :quit
    _ -> do hPutStrLn handle line
            interactWithUser handle -- send, then continue looping
Run Code Online (Sandbox Code Playgroud)

Dul*_*gon 5

\xc3\x98rjan Johansen \ 的帮助下我弄清楚了。forkFinally在主线程关闭后创建一个线程。该行本来要等到talk完成然后关闭连接。它必须是(也缩短了它)

\n\n
main :: IO ()\nmain = withSocketsDo $ do\n  handle <- connectTo "192.168.137.1" (PortNumber 44444)\n  talk handle `finally` hClose handle\n\ntalk :: Handle -> IO ()\ntalk handle = do\n    hSetNewlineMode handle universalNewlineMode\n    hSetBuffering handle LineBuffering\n    _ <- race fromServer toServer\n    return ()\n  where\n    fromServer = forever $ do\n      line <- hGetLine handle\n      print line\n    toServer = do\n      line <- getLine\n      case line of\n-- server accepts /quit as disconnect command so better send it to the server \n        ":quit" -> do hPutStrLn handle "/quit"; return "Quit"\n        _ ->  do hPutStrLn handle line; toServer\n
Run Code Online (Sandbox Code Playgroud)\n\n

我希望这段代码是安全的:D

\n