Haskell 他为什么不回来?

Haskell 他为什么不回来?,haskell,client-server,handle,Haskell,Client Server,Handle,我正在使用Haskell的网络库创建一个简单的聊天服务器。服务器必须做两件事: 每隔n滴答声向当前连接的所有客户端广播一条消息 从客户端接收发送到服务器的任何消息 服务器和客户端定义为 data Server = Server { sSocket :: Socket, sPort :: Port, sClients :: MVar (Set.Set ClientAddress) } newtype ClientAddress = ClientAddress (Handle,

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

  • 每隔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

我遇到的问题是,从客户端接收消息似乎会阻塞。我通过检查句柄是否包含内容来接收消息

serve :: ClientAddress -> IO ()
serve (ClientAddress (handle, host, port)) = do
  b <- hIsEOF handle
  putStrLn $ show $ b -- <-- It never makes it this far...
service::ClientAddress->IO()
服务(客户端地址(句柄、主机、端口))=do
b在他的
中,我发现:

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

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

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

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


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

您能捕获并打印出异常吗?您可以使用
Control.Exception.try
来执行此操作,方法是:
try(hIsEOF handle)::IO(SomeException Bool)
它不会通过允许我打印任何内容的尝试。如果我在
try…
之前放置一个print语句,它会显示,但不会在之后显示。您链接的文档确实会说“注意:hIsEOF可能会阻塞,因为它必须尝试从流中读取,以确定是否还有更多的数据要读取。”如果
try
阻塞,则这意味着它不是例外
try
设计用于在出现异常时立即返回。这表明@rjanJohansen是正确的,它正在阻止从流中读取。您能捕获并打印出异常吗?您可以使用
Control.Exception.try
来执行此操作,方法是:
try(hIsEOF handle)::IO(SomeException Bool)
它不会通过允许我打印任何内容的尝试。如果我在
try…
之前放置一个print语句,它会显示,但不会在之后显示。您链接的文档确实会说“注意:hIsEOF可能会阻塞,因为它必须尝试从流中读取,以确定是否还有更多的数据要读取。”如果
try
阻塞,则这意味着它不是例外
try
设计用于在出现异常时立即返回。这表明@rjanJohansen是正确的,它在读流时阻塞了。谢谢,你们三个是正确的,它阻塞了。谢谢,你们三个是正确的,它阻塞了。
serve :: ClientAddress -> IO ()
serve (ClientAddress (handle, host, port)) = do
  b <- hIsEOF handle
  putStrLn $ show $ b -- <-- It never makes it this far...