【问题标题】:Why does hIsEOF not return?为什么hIsEOF不返回?
【发布时间】:2014-08-04 21:38:58
【问题描述】:

我正在使用 Haskell 的 Network 库创建一个简单的聊天服务器。服务器必须做两件事:

  • n 个滴答声向所有当前连接的客户端广播一条消息
  • 接收来自客户端发送到服务器的任何消息。

服务器和客户端定义为

data Server = Server {
  sSocket :: Socket,
  sPort :: Port,
  sClients :: MVar (Set.Set ClientAddress)
  }

newtype ClientAddress = ClientAddress (Handle, HostName, PortNumber) 
                          deriving (Show)

通过运行以下函数来构建服务器

startServer :: Port -> IO ThreadId -- 
startServer port = withSocketsDo $ do
  socket  <- listenOn $ PortNumber $ fromIntegral port  
  clients <- newMVar Set.empty
  let server = Server socket port clients
  forkIO $ forever $ do
    client@(handle, host, port) <- accept socket
    modifyMVar_ clients (\cs -> return $ Set.insert (ClientAddress client) cs)
    forkIO $ forever $ serve $ ClientAddress client
  forkIO $ forever $ sendServerUpdates 1000000 server

请注意,最后两行分叉了两个不同的线程:第一个用于处理客户端连接并“提供”它们的消息,第二个用于向客户端发送服务器广播。

向客户广播的工作如下

sendServerUpdates :: Microsecond -> Server -> IO ()
sendServerUpdates frequency server = do
  withMVar (sClients server) (mapM_ sendServerUpdate)
  threadDelay frequency

sendServerUpdate :: ClientAddress -> IO ()
sendServerUpdate (ClientAddress (handle, host, port)) = do
  putStrLn "Sending update."

我遇到的问题是,从客户端接收消息似乎被阻止了。我通过检查句柄是否有内容来接收消息

serve :: ClientAddress -> IO ()
serve (ClientAddress (handle, host, port)) = do
  b <- hIsEOF handle
  putStrLn $ show $ b -- <-- It never makes it this far...

不幸的是,代码从来没有进入第二行调用putStrLnhIsEOF 似乎遇到了一些异常,although the documentation doesn't seem to mention it

为什么我的代码永远阻塞在hIsEOF

【问题讨论】:

  • 你能捕捉并打印出异常吗?您可以使用Control.Exception.try 来执行此操作:try (hIsEOF handle) :: IO (Either SomeException Bool)
  • 它没有通过尝试让我打印任何东西。如果我在try ... 之前放置一个打印语句,它会显示,但之后不会。
  • 您链接的文档确实说“注意:hIsEOF 可能会阻塞,因为它必须尝试从流中读取以确定是否还有要读取的数据。”
  • 如果try 阻塞,那么这意味着它不是一个例外。 try 旨在在出现异常时立即返回。这表明@ØrjanJohansen 是正确的,它阻止了从流中读取。

标签: haskell client-server handle


【解决方案1】:

hIsEOFdocumentation 中,我发现了以下内容:

注意:hIsEOF 可能会阻塞,因为它必须尝试从 流来确定是否还有要读取的数据。

我没想到会这样。我想知道hReadyhGetBufNonBlocking 是否更好?我从未在 Haskell 中尝试过整个非阻塞 IO 位。

【讨论】:

  • 谢谢,你们三个是正确的,它被阻止了。
猜你喜欢
  • 2017-10-08
  • 2014-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-30
  • 1970-01-01
  • 2020-02-12
相关资源
最近更新 更多