use*_*455 9 networking haskell
我正在尝试让多个客户端连接到服务器.我设法做的是通过使用服务器将一个客户端连接到服务器:
main = withSocketsDo $ do
socket <- listenOn port
(handle, host, portno) <- accept socket
hSetBuffering handle LineBuffering
msg <- hGetLine handle
putStrLn $ "The client says: " ++ msg
hClose handle
sClose socket
putStrLn "Server is done."
Run Code Online (Sandbox Code Playgroud)
并为客户:
main = withSocketsDo $ do
handle <- connectTo "localhost" port
hSetBuffering handle LineBuffering
hPutStrLn handle "Hello!"
hClose handle
Run Code Online (Sandbox Code Playgroud)
这些显然仅用于测试目的;)
现在,我已经读过我需要使用forkIO来使多个客户端连接到这个服务器.但是我无法找到如何使用forkIO或如何管理将要连接的多个客户端.有人可以向我解释我应该做些什么吗?
提前致谢!
ham*_*mar 10
关键是,一旦你接受了使用连接accept,你就会想要在主线程回到监听时分叉一个新线程来处理连接.所以这样的事情应该可以解决问题.
main = withSocketsDo $ do
socket <- listenOn port
-- We want to accept multiple connections,
-- so we need to accept in a loop
forever $ do
(handle, host, portno) <- accept socket
-- But once we've accepted, we want to go off and handle the
-- connection in a separate thread
forkIO $ do
hSetBuffering handle LineBuffering
msg <- hGetLine handle
putStrLn $ "The client says: " ++ msg
hClose handle
Run Code Online (Sandbox Code Playgroud)
请注意,这样服务器会一直运行,直到您终止进程,这是许多服务器的常见行为.实现更优雅的关闭将需要使用MVars或STM进行一些跨线程通信.
就像一般风格的评论一样,我将服务器对客户端连接的反应拆分为一个单独的函数.这使我更容易阅读
main = withSocketsDo $ do
socket <- listenOn port
accept socket >>= handleClientRequest socket
handleClientRequest socket (handle, host, portno) = do
hSetBuffering handle LineBuffering
msg <- hGetLine handle
putStrLn $ "The client says: " ++ msg
hClose handle
sClose socket
putStrLn "Server is done."
Run Code Online (Sandbox Code Playgroud)
现在我们可能希望它无限循环,因为这往往是大多数服务器的工作方式.所以我们永远使用(来自Control.Monad)
main = withSocketsDo $ do
socket <- listenOn port
forever $ accept socket >>= handleClientRequest socket
handleClientRequest socket (handle, host, portno) = do
hSetBuffering handle LineBuffering
msg <- hGetLine handle
putStrLn $ "The client says: " ++ msg
hClose handle
sClose socket
putStrLn "Server is done."
Run Code Online (Sandbox Code Playgroud)
从这里开始,使用forkIO的方式变得非常清楚
main = withSocketsDo $ do
socket <- listenOn port
forever $ accept socket >>= forkIO . (handleClientRequest socket)
handleClientRequest socket (handle, host, portno) = do
hSetBuffering handle LineBuffering
msg <- hGetLine handle
putStrLn $ "The client says: " ++ msg
hClose handle
sClose socket
putStrLn "Server is done."
Run Code Online (Sandbox Code Playgroud)