简体   繁体   English

为什么hIsEOF不会返回?

[英]Why does hIsEOF not return?

I am creating a simple chat server using Haskell's Network library. 我正在使用Haskell的Network库创建一个简单的聊天服务器。 The server has to do two things: 服务器必须做两件事:

  • Broadcast a message every n ticks to all of the currently connected clients n个刻度向所有当前连接的客户端广播消息
  • Receive any messages from the clients sent to the server. 从发送到服务器的客户端接收任何消息。

The server and client are defined as 服务器和客户端定义为

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

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

A server is constructed by running the following function 通过运行以下函数构造服务器

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

Note that the last two lines fork two different threads: the first for handling client connections and "serving" their messages, and the second for sending server broadcasts to the clients. 请注意,最后两行分叉两个不同的线程:第一个用于处理客户端连接和“提供”其消息,第二个用于将服务器广播发送到客户端。

Broadcasting to the clients works as follows 广播给客户的工作如下

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."

The issue I have, is that receiving messages from the clients seem to block. 我遇到的问题是,从客户端接收消息似乎阻止了。 I receive messages by checking if the handle has contents 我通过检查句柄是否有内容来接收消息

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

Unfortunately, the code never makes it to the second line to call the putStrLn . 不幸的是,代码永远不会到第二行调用putStrLn It seems like hIsEOF encounters some exception, although the documentation doesn't seem to mention it . 似乎hIsEOF遇到了一些例外, 虽然文档似乎没有提到它

Why does my code block on hIsEOF forever? 为什么我的代码hIsEOF永久阻止hIsEOF

In hIsEOF 's documentation I found the following: hIsEOF文档中,我发现了以下内容:

NOTE: hIsEOF may block, because it has to attempt to read from the stream to determine whether there is any more data to be read. 注意:hIsEOF可能会阻塞,因为它必须尝试从流中读取以确定是否还有更多数据要读取。

I wouldn't have expected this. 我不会想到这一点。 I wonder if hReady or hGetBufNonBlocking are any better? 我想知道hReadyhGetBufNonBlocking是否更好? I've never tried the whole non-blocking IO bit in Haskell. 我从来没有尝试过Haskell中的整个非阻塞IO位。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM