1

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)

これを修正するにはどうすればよいですか?サーバーを拡張して、さらに学習できるようにしたいと考えています。ありがとう!

4

1 に答える 1

4

この場合、問題は単純です。サーバーに echo コマンド、次に add コマンドを書き込んでから、切断しています。次に、サーバーは echo コマンドを処理しようとし、クライアントに書き戻そうとしますが、クライアントは既に切断されています! したがって、例外が発生します。

クライアントは、サーバーから十分なデータを読み取るまで切断できません。また、クライアントの切断によってサーバーが強制終了されないように、サーバーは例外を処理する必要があります。

于 2011-04-08T21:35:05.293 に答える