L01*_*man 14 haskell network-programming lazy-evaluation
我使用Network,并Gloss在哈斯克尔游戏服务器.它工作正常,除了客户端必须关闭服务器以接收它发送的数据.我打赌这是一个懒惰的案例......
极简主义服务器:
import Network
import System.IO
main = do
sock <- listenOn (PortNumber (fromIntegral 12345))
loop sock
loop sock = do
(hIn, _, _) <- accept sock
str <- hGetContents hIn
print str
loop sock
Run Code Online (Sandbox Code Playgroud)
极简主义客户:
import Network
import System.IO
import Graphics.Gloss.Interface.IO.Game
main = playIO
(InWindow "Test Multi" (500, 500) (500, 500))
white
60
Nothing
draw
(\_ x -> return x)
advance
draw Nothing = return blank
draw (Just x) = return (Text (show x))
advance _ Nothing = do
hOut <- connectTo "000.000.0.0" (PortNumber (fromIntegral 12345))
hSetBuffering hOut NoBuffering
hPutStr hOut "Hello!"
return (Just hOut)
advance _ x = return x
Run Code Online (Sandbox Code Playgroud)
我启动服务器,等待10秒,然后启动客户端,等待15秒,看到服务器上没有任何反应,关闭客户端,看到"你好!" 突然出现在服务器上.我想"你好!" 在客户端正在运行时,在advance通话中出现,否则我无法进行多人游戏(呜咽)!
但是,如果我将客户端的代码更改为
main = loop Nothing
loop x = do
x' <- advance 0 x
getLine
Run Code Online (Sandbox Code Playgroud)
服务员立即显示"你好!" 而客户端正在等待我的输入.
我按照另一个问题的建议尝试使用爆炸模式和hClose:
-- ...
!str <- hGetContents hIn
hClose hIn
-- ...
Run Code Online (Sandbox Code Playgroud)
这使得输出立即显示,而不会关闭客户端.那很棒.但是,我打算使用字节串,因为我向服务器发送的数据是系列化的,所以我import qualified Data.ByteString as B并更改hGetContents到B.hGetContents,这使得该问题再次出现.
问题确实是一种懒惰的情况.hGetContents懒惰读取所有内容Handle,因此只有当它关闭时,客户端才会中止连接.相反,我使用hGetLine它返回每次遇到a时的内容\n,我将其用作end-of-message标记.
我可能完全错了,但问题不是hGetContents?当然应该等到通过套接字发送的所有内容在下一行(打印...)开始之前到达.hGetContents 旨在为您提供在套接字关闭之前发送的所有内容.像hGetLine这样的东西可以直接终止,你可以让套接字打开以便稍后发送更多数据.然后,您的客户端可以使用hPutStrLn而不是hPutStr.
| 归档时间: |
|
| 查看次数: |
1889 次 |
| 最近记录: |