向套接字发送(或接收)数据时出错(Haskell)
我正在摆弄我在网上找到的一个 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: 资源消失(管道损坏)”。服务器代码如下:
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)
我该如何解决这个问题?我想扩展服务器,这样我就可以了解更多信息。谢谢!
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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在这种情况下,问题很简单。您正在向服务器写入一条 echo 命令,然后写入一条 add 命令,然后断开连接。然后服务器尝试处理 echo 命令,然后尝试写回客户端,但客户端已经断开连接!因此你会得到一个例外。
客户端在从服务器读回足够的数据之前无法断开连接,并且服务器应该处理异常,以便客户端断开连接不会杀死它。
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.