Haskell中的非阻塞UDP接收

7
我是一名有用的助手,可以为您翻译文本。

我仍在学习Haskell的基础知识,目前正在将一些Java代码移植到Haskell中。 我目前遇到的问题是使用Network.Socket.ByteString中的UDP recvFrom。

问题出在this method上:

public abstract SocketAddress receive(ByteBuffer dst) throws IOException

Receives a datagram via this channel.
If a datagram is immediately available, or if this channel
is in blocking mode and one eventually becomes available,
then the datagram is copied into the given byte buffer and
its source address is returned. If this channel is in
non-blocking mode and a datagram is not immediately available
then this method immediately returns null.

问题是,当我使用Network.Socket.ByteString.recvFrom时,我的代码会在此处阻塞等待数据包到来。它不会返回类似Maybe的东西来指示是否接收了某些内容(就像Java中没有可用数据时返回null一样)。
我找到了这个线程:https://mail.haskell.org/pipermail/haskell-cafe/2010-August/082725.html 在其末尾有几种建议:1)FFI 2)在自己的线程中运行recvFrom
我不确定我能够在此时使用任何一种方法(知识不足)。我想要的是获得类似于Java的非阻塞接收方式:如果可用所需信息,则获取它,否则什么也不做。有人可以指出什么是更好的方法吗?有任何代码片段,有人已经处理过这个问题吗?

1
请参考如何在Haskell中观察多个文件/套接字变为可读/可写?;但我了解移植过程中的重组可能会非常破坏性和危险。长期来看,将接收放到单独的线程中是正确的解决方案。当然,您可以以非阻塞方式与单独的线程通信。 - Daniel Wagner
1个回答

4
您可以使用socketToHandlehGetNonBlocking一起使用:
recvNonBlocking :: Socket -> Int -> IO ByteString
recvNonBlocking s n = do
     hnd <- socketToHandle s ReadMode 
     hGetNonBlocking hnd n

但请记住,在调用 socketToHandle 后您不能再使用 Socket,因此仅当您无论如何都会在之后关闭 Socket 时才可行。


注意:在Windows和除GHC以外的Haskell实现中,此函数无法正常工作;它的行为与hGet完全相同。 - palik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接