|import Control.Concurrent (forkIO, killThread)|
|import Control.Monad.IO.Class (MonadIO, liftIO)|
|import Network (connectTo, PortID (..))|
|import System.Environment (getArgs, getProgName)|
|main :: IO ()|
|main = do|
|args <- getArgs|
|case args of|
|[host, port] -> telnet host (read port :: Int)|
|_ -> usageExit|
|usageExit = do|
|name <- getProgName|
|putStrLn $ "Usage : " ++ name ++ " host port"|
|telnet :: String -> Int -> IO ()|
|telnet host port = runResourceT $ do|
|(releaseSock, hsock) <- allocate (connectTo host $ PortNumber $ fromIntegral port) hClose|
|liftIO $ mapM_ (`hSetBuffering` LineBuffering) [ stdin, stdout, hsock ]|
|(releaseThread, _) <- allocate (forkIO $ runResourceT $ sourceHandle stdin $$ sinkHandle hsock) killThread|
|sourceHandle hsock $$ sinkHandle stdout|
Thanks for sharing this example. I stumbled upon it while learning about implementing telnet chat servers with Haskell. I know it has been several years since you posted this example, but out of curiousity, did you encounter any problems with this client truncating the output? I built a chat-server based on an example that I found on HaskellWiki. The server works well with the telnet client supplied with OSX. I also produced a telnet client using your example, and I found that the client truncates the output. For example, if a user enters "Hello World", the output is "Hello Worl". So, the last character is always truncated.
I have been digging into the packages used in the example to determine if something might be truncating the output. My thought is that perhaps one of the input or output handles is truncating the bytestring from stdin? But I am fairly new to Haskell, so it is a bit above my head. If you have any thoughts, please let me know.
Running with GHC, the code above gives a conflict on line 26.
Replacing it with the following solves the issue:
liftIO $ Prelude.mapM_ (`hSetBuffering` LineBuffering) [ stdin, stdout, hsock ]