4

我一直在使用 reflex 和 reflex-dom 来重新创建棋盘游戏的 web 版本,到目前为止我非常喜欢它,但是我需要一个 websocket 来在其他玩家移动时提醒玩家。

一切正常,但如果服务器出现故障,我找不到检测它发生并重新连接的方法。此外,如果您在服务器关闭时向服务器发送事件,它只会被吃掉而没有任何错误。

我正在使用来自https://github.com/reflex-frp/reflex-examples/blob/master/websocket-echo/src/Main.hs的 websockets 示例的精简版本

{-# 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 来发送超时的ping,比如一些动态的返回websockets,然后如果ping 持续了一定时间而没有响应则重新连接?但我无法想象重新连接的代码会是什么样子。

编辑:当 websocket 仍处于挂起状态时,reflex-dom 发送事件是一个问题。我提出了拉取请求,尽管我觉得某处有更好的解决方案。

4

2 回答 2

1

编辑:当 websocket 仍处于挂起状态时,reflex-dom 发送事件是一个问题。我提出了拉取请求,尽管我觉得某处有更好的解决方案。

仅供参考,自从发布问题以来,WebSocket API 的一些非常相关的扩展已合并到 reflex-dom 中:

我相信 close 事件正是您想要的。它当时不可用。

于 2017-03-05T20:45:33.490 回答
1

看起来当 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

您可能应该在他们的问题跟踪器上打开一个问题。或者只是找到更好的图书馆。

于 2016-03-04T17:55:02.800 回答