能够在snaplet中使用Network.WebSockets
模块会很高兴,但我无法弄清楚如何实际操作。
使用runWebSocketsSnap :: MonadSnap m => ServerApp -> m ()
中的Network.WebSockets.Snap
函数,很容易在我的应用中包含一个简单的无状态websocket服务器:
routes :: [(ByteString, Handler App App ())]
routes = [ ("/ws", runWebSocketsSnap wsApp) ]
wsApp :: PendingConnection -> IO () -- this is the ServerApp type
wsApp pending = do
conn <- acceptRequest pending
forever $ do
msg <- receiveData conn
sendTextData conn ("Echo " `mappend` msg :: Text)
但我的目标是维护webscket服务器的状态(例如,连接的客户端列表,如http://jaspervdj.be/websockets/example.html)。或者,访问snaplet的酸状态存储器会很棒。
我的第一个想法是liftIO
对Handler App App
monad中的websocket操作,并编写这样的应用程序:
wsApp :: PendingConnection -> Handler App App ()
wsApp pending = do
conn <- liftIO $ acceptRequest pending
forever $ do
msg <- liftIO $ receiveData conn
update (SetLastMsg msg)
liftIO $ sendTextData conn ("Stored msg in datastore.")
但是没有runWebSocketsSnap
版本可以使用上述形式的应用,而我无法弄清楚如何修改现有版本(source on hackage)。在我看来,我需要一个替代forkIO
代替Handler App App
monad中的一个动作,但我对Haskell的理解,特别是Snap中的并发性在这里结束......
答案 0 :(得分:4)
runWebSocketsSnap函数要求其参数的类型为PendingConnection -> IO ()
。这意味着您无法直接访问该功能内部的App数据结构。您需要做的是将信息作为参数传递给函数。
routes = [ ("/ws", webSocketsDriver) ]
webSocketsDriver :: Handler App App ()
webSocketsDriver = do
appState <- get
runWebSocketsSnap (wsApp appState)
wsApp :: App -> PendingConnection -> IO ()
wsApp app pending = do
...