向套接字发送(或接收)数据时出错(Haskell)

时间:2011-04-08 20:59:03

标签: sockets networking haskell io echo-server

我正在乱搞我在网上找到的一个echo服务器,试图用Haskell来感受网络编程,我正在遇到绊脚石。我似乎无法弄清楚如何将数据发送到服务器(通过其他程序或任何其他方式)。我目前的尝试如下:

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

当我运行main时,我在服务器运行的终端中收到错误“Server.hs :: hPutChar:resource vanished(Broken pipe)”。服务器代码如下:

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)

我该如何解决这个问题?我想扩展服务器,以便我可以学到更多。谢谢!

1 个答案:

答案 0 :(得分:4)

在这种情况下,问题很简单。您正在向服务器写入echo命令,然后是add命令,然后断开连接。然后服务器尝试处理echo命令,然后它尝试写回客户端,但客户端已经断开连接!因此你得到一个例外。

客户端无法断开连接,直到从服务器读回足够的数据 - 服务器应处理异常,以便客户端断开连接不会将其终止。