首页 > 解决方案 > 无法将多个客户端与 Haskell Websocket 服务器一起使用

问题描述

我正在尝试使用 websockets 测试我的游戏服务器,但我在使用多个客户端时遇到问题。连接它们中的每一个都可以正常工作,但是当我启动游戏并通过套接字发送第一条消息时,它们会引发“ConnectionClosed”错误。

服务器代码如下所示:

main :: IO ()
main = do
    state <- newMVar []
    putStrLn "listening"
    WS.runServer "127.0.0.1" 9000 $ \pen -> do
        c <- WS.acceptRequest pen
        putStrLn "user connected"
        cs <- takeMVar state
        let cs' = c : cs
        case Vector.fromList cs' :: Maybe (Vector.Vector 4 WS.Connection) of
            Just v -> do
                let
                    us = Vector.imap
                        (\i x -> websocketUser x ("websocket user " ++ show i))
                        v
                putMVar state []
                g <- exampleGame us
                _ <- playGame g
                return ()
            Nothing -> putMVar state cs'

为了测试这一点,我打开了 4 个 chrome 选项卡并将每个选项卡连接到服务器。对于我连接的每个选项卡,服务器都会打印“用户连接”行,在 4 次连接后游戏应该开始,但所有套接字都断开连接。如果我只连接一个客户端,它确实可以正常工作。所以我认为问题在于我连接来自同一台机器的所有客户端。但是我不知道如何在不使用多个设备的情况下进行测试。我已经尝试为每个客户端使用不同的浏览器和端口。

我的问题:这是由来自同一台机器和 chrome 的所有客户端连接还是服务器重用现有连接或类似的东西引起的,如果是,我该如何解决这个问题,以便我可以在本地测试我的游戏?还是我的 Haskell 代码有问题?

网络套接字库

矢量大小

标签: haskellwebsocket

解决方案


请参阅ServerApp类型的文档。IO 操作完成后,底层套接字将关闭。因此,您的前三个客户端中的每一个都接受一个连接,将连接存储在 中state,然后完成,关闭连接。只有第四个客户端保持它的连接打开,它不能对其他三个连接做任何有用的事情,这些连接现在已经关闭。

如果将最后一行替换为:

Nothing -> do
    putMVar state cs'
    threadDelay (10^9)  -- wait a while

那么这可能会使所有四个客户端都连接起来。

要“真正地”解决这个问题,您可以让前三个连接永远等待,然后安排第四个线程在游戏结束时杀死它们。

但是,我不确定这是正确的架构。您可能希望每个连接线程进入一个循环来处理来自其客户端的传入消息,而不是让唯一的第四个连接线程运行并轮询所有四个连接。这些线程可以修改共享游戏状态和/或直接向其他客户端广播消息(如websockets文档中的示例“聊天”程序),或者将传入消息排队以供单独的游戏线程处理。


推荐阅读