Я пытаюсь прослушать дейтаграммы UDP всего за 3 секунды в Haskell. Я написал код, но не уверен, почему он не работает. Я установил тайм-аут на 3 секунды, но он просто ждет вечно и не блокируется
import Control.Concurrent as CC (forkIO, threadDelay, killThread)
import qualified Data.ByteString.Char8 as C
import Network.Socket
import Network.Socket.ByteString as B
import Data.IORef
import Control.Monad (forever)
import System.Timeout
receiveDatagram = do
ack <- newIORef (0 :: Int)
addrinfos <- getAddrInfo Nothing (Just "127.0.0.1") (Just "7001")
let serveraddr = head addrinfos
sock <- socket (addrFamily serveraddr) Datagram defaultProtocol
bind sock (addrAddress serveraddr)
print "starting"
tmp <- timeout 3000000 (do
(msg, addr) <- B.recvFrom sock 1024
close sock
writeIORef ack 1
print msg
)
case tmp of
Nothing -> close sock
_ -> print "something else"
print "timeout done"
В документации к timeout сказано:
Standard I/O functions like hGetBuf, hPutBuf, Network.Socket.accept, or hWaitForInput appear to be blocking, but they really don't because the runtime system uses scheduling mechanisms like select(2) to perform asynchronous I/O, so it is possible to interrupt standard socket I/O or file I/O using this combinator.
Он отлично работает для меня. Как вы его составляете? Какая платформа? Какая версия GHC? Обновлено: я использовал GHC 8.4.4 на OS-X. EDIT2: GHC 8.2.0 в Linux также работал нормально.
Это может иметь значение, используется ли поточная среда выполнения или нет, но я отказался от попыток отследить реализацию recvFrom в определенный момент.
Я использую GHCi версии 8.4.4 со стеком в качестве инструмента построения под Windows 10.
@chi Изначально у меня был оператор close под таймаутом, но я 1000 раз менял код, потому что думал, что не закрываю сокет в нужное время
И версия стека: Версия 1.7.1, версия Git 681c800873816c022739ca7ed14755e85a579565 (5807 коммитов) x86_64 hpack-0.28.2
Я предполагаю, что это проблема Windows + GHCi, которую я не могу проверить. Попробуйте скомпилировать его, а не интерпретировать (так, ghc file.hs -o file вместо ghci file.hs). Если это сработает, у вас есть способ продолжить разработку. В любом случае я предлагаю вам отправить проблему на ghchq.





Лично мне не нравится идея, лежащая в основе
timeout, или ее использование в приведенном выше коде. Что, еслиrecvFromзавершится успешно, и сразу после этого истечет время ожидания, скажем, доclose(или даже доwriteIORef)? Мы потребляем сообщение из буфера ОС, ноtmpсообщит оNothing, потеряв сообщение (иackвсе еще может быть нулевым).