Обнаружить закрытое соединение с сервером через веб-сокеты в reflex-dom?
Я использовал reflex и reflex-dom для воссоздания веб-версии настольной игры, и мне это до сих пор нравится, но мне требуется веб-розетка, чтобы предупредить игрока, когда другой игрок сделал ход.
Все работает отлично, но если сервер выходит из строя, я не могу найти способ обнаружить, что это произошло, и восстановить соединение. Кроме того, если вы отправляете событие на сервер, когда оно не работает, оно просто съедается без ошибок.
Я использую урезанную версию примера websockets от https://github.com/reflex-frp/reflex-examples/blob/master/websocket-echo/src/Main.hs
{-# LANGUAGE RecursiveDo #-}
module Lib where
import Data.Monoid
import Reflex.Dom
import qualified Data.Text as T
import Data.Text.Encoding (encodeUtf8, decodeUtf8)
wsurl = "ws://127.0.0.1:5714"
-- wsurl = "ws://echo.websocket.org"
someFunc = mainWidget $ do
rec t <- textInput $ def & setValue .~ fmap (const "") newMessage
b <- button "Send"
text $ "Sending to " <> wsurl
let newMessage = fmap ((:[]) . encodeUtf8 . T.pack) $ tag (current $ value t) $ leftmost [b, textInputGetEnter t]
ws <- webSocket wsurl $ def & webSocketConfig_send .~ newMessage
receivedMessages <- foldDyn (\m ms -> ms ++ [m]) [] $ _webSocket_recv ws
el "p" $ text "Responses from :"
_ <- el "ul" $ simpleList receivedMessages $ \m -> el "li" $ dynText =<< mapDyn (T.unpack . decodeUtf8) m
return ()
Я чувствую, что должен быть способ сделать это с помощью tickLossy для отправки пингов с тайм-аутом, как какая-то динамика, которая возвращает веб-сокеты, а затем повторно подключается, если пинг проходит определенное количество времени без ответа? Но мне трудно представить, как будет выглядеть код для повторного подключения.
Редактировать: это была проблема с reflex-dom, отправляющим событие, пока веб-сокет все еще находился в состоянии ожидания. Я сделал запрос извлечения, хотя я чувствую, что где-то есть лучшее решение.
2 ответа
Редактировать: это была проблема с reflex-dom, отправляющим событие, пока веб-сокет все еще находился в состоянии ожидания. Я сделал запрос извлечения, хотя я чувствую, что где-то есть лучшее решение.
Только к вашему сведению, с тех пор, как вопрос был опубликован, в API WebSocket были объединены некоторые весьма важные расширения: reflex-dom:
- Вы можете закрыть веб-сокеты через
Event
с, см_webSocketConfig_close
- Вы можете указать, хотите ли вы автоматически переподключиться, см.
_webSocketConfig_reconnect
- есть
Event
выставлено, когда соединение закрыто, см._webSocket_close
- есть
Event
для того, когда возникает ошибка, см._webSocket_error
Я полагаю, что это именно то, что вы искали. Это было просто не доступно в то время.
Похоже на то, когда websocket закрывается, библиотека пытается восстановить соединение:
start = do
ws <- liftIO $ newWebSocket wv url onMessage onOpen $ do
void $ forkIO $ do --TODO: Is the fork necessary, or do event handlers run in their own threads automatically?
liftIO $ writeIORef currentSocketRef Nothing
liftIO $ threadDelay 1000000
start
liftIO $ writeIORef currentSocketRef $ Just ws
return ()
(newWebSocket
принимает onClose
обработчик события в последнем аргументе)
И все сообщения, которые вы отправляете при переподключении, игнорируются:
performEvent_ $ ffor (_webSocketConfig_send config) $ \payloads -> forM_ payloads $ \payload -> do
mws <- liftIO $ readIORef currentSocketRef
case mws of
Nothing -> return () -- Discard --TODO: should we do something better here? probably buffer it, since we handle reconnection logic; how do we verify that the server has received things?
Just ws -> do
liftIO $ webSocketSend ws payload
Вы, вероятно, должны открыть проблему на их трекере. Или просто найдите лучшую библиотеку.