Simple TCP Client

I am trying to implement a simple TCP client in Haskell. But it closes as soon as it connects. I do not know what makes it close. How can I make it print lines from the server to stdout and send lines from stdin to the server forever, until stdin receives the line ": quit"?

 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 
+6
source share
1 answer

Using Ørjan Johansen , I figured this out. forkFinally created the thread, after which the main thread was closed. This line was supposed to wait for the talk to complete, and then close the connection. It should have been (also abbreviated)

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

I hope this code is safe: D

+4
source

Source: https://habr.com/ru/post/973604/


All Articles