Search code examples
socketsnetwork-programminghaskellioecho-server

Error in Sending (or Receiving) Data to Socket (Haskell)


I'm messing around with an echo server I found online, trying to get a feel for network programming with Haskell, and I'm hitting a stumbling block. I can't seem to figure out how to send data to the server (via another program or any other means). My current attempt is as follows:

import Network (connectTo, Socket, PortID(..))
import System.IO (hPutStrLn, hClose, hSetBuffering, BufferMode(..))

main :: IO ()
main = do
  handle <- connectTo "127.0.0.1" (PortNumber 5555)
  hSetBuffering handle LineBuffering
  hPutStrLn handle "echo hello, world!"
  hPutStrLn handle "add 1 2"
  hClose handle

When I run main, I get the error "Server.hs: : hPutChar: resource vanished (Broken pipe)" in the terminal in which the server is running. The server code is as follows:

import Network   (listenOn, accept, withSocketsDo, PortID(..), Socket)
import System    (getArgs)
import System.IO (hSetBuffering, hGetLine, hPutStrLn, BufferMode(..), Handle)
import Control.Concurrent (forkIO)

main :: IO ()
main = withSocketsDo $ do 
  args <- getArgs
  let port = fromIntegral (read $ head args :: Int)
  sock <- listenOn $ PortNumber port
  putStrLn $ "Listening on " ++ show port
  sockHandler sock

sockHandler :: Socket -> IO ()
sockHandler sock = do
  (handle, _, _) <- accept sock
  hSetBuffering handle NoBuffering
  forkIO $ commandProcessor handle
  sockHandler sock

commandProcessor :: Handle -> IO ()
commandProcessor handle = do
  line <- hGetLine handle
  let cmd = words line
  case (head cmd) of
    ("echo") -> echoCommand handle cmd
    ("add")  -> addCommand handle cmd
    _        -> do hPutStrLn handle "Unknown command."
  commandProcessor handle

echoCommand :: Handle -> [String] -> IO ()
echoCommand handle cmd = do
  hPutStrLn handle (unwords $ tail cmd)

addCommand :: Handle -> [String] -> IO ()
addCommand handle cmd = do
  hPutStrLn handle $ show $ (read $ cmd !! 1) + (read $ cmd !! 2)

How do I go about fixing this? I want to get to extending the server so I can learn some more. Thanks!


Solution

  • In this instance, the problem is simple. You're writing to the server an echo command, and then an add command, and then disconnecting. The server then tries to process the echo command, and then it tries to write back to the client, but the client already disconnected! hence you get an exception.

    The client can't disconnect until it reads back enough data from the server -- and the server should handle exceptions so that a client disconnect doesn't kill it.