2011-04-08 70 views
1

我在網上找到一個echo服務器,試圖感受一下Haskell網絡編程的感覺,而且我正在碰到一個絆腳石。我似乎無法弄清楚如何將數據發送到服務器(通過其他程序或任何其他方式)。我現在嘗試如下:向Socket(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 

當我運行主,我得到的錯誤「Server.hs:hPutChar:資源消失(管道中斷)」,在終端中的服務器運行。服務器代碼如下:

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) 

我該如何解決這個問題?我想擴展服務器,所以我可以學到更多。謝謝!

回答

4

在這種情況下,問題很簡單。您正在向服務器寫入一個echo命令,然後是一個添加命令,然後斷開連接。然後服務器嘗試處理echo命令,然後嘗試寫回客戶端,但客戶端已斷開連接!因此你會得到一個例外。

客戶端在從服務器讀回足夠的數據之前不能斷開連接 - 服務器應該處理異常,以便客戶端斷開連接不會終止它。

相關問題