我正在尝试使用 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 个连接后,游戏应该开始,但所有套接字都会断开连接。如果我只连接一个客户端,它确实工作正常。所以我认为问题是我从同一台机器连接所有客户端。但是我不知道如何在不使用多个设备的情况下测试它。我已经尝试为每个客户端使用不同的浏览器和端口。
我的问题: 这是由于从同一台计算机连接所有客户端而导致的吗?或者服务器重用现有连接或类似的东西,如果是,我该如何解决这个问题,以便我可以在本地测试我的游戏? 或者我的 Haskell 代码有问题吗?
最佳答案
请参阅 ServerApp
type 的文档。一旦 IO 操作完成,底层套接字就会关闭。因此,前三个客户端中的每一个都接受一个连接,将连接存储在 state
中,然后完成并关闭连接。只有第四个客户端保持其连接打开,并且它无法对其他三个连接执行任何有用的操作,这些连接现已关闭。
如果将最后一行替换为:
Nothing -> do
putMVar state cs'
threadDelay (10^9) -- wait a while
然后这可能会让所有四个客户端都连接起来。
要“真正”解决此问题,您可以让前三个连接永远等待,然后安排第四个线程在游戏结束时杀死它们。
但是,我不确定这是否是正确的架构。您可能希望每个连接线程进入一个循环来处理来自其客户端的传入消息,而不是仅运行第四个连接线程并轮询所有四个连接。这些线程可以修改共享游戏状态和/或直接向其他客户端广播消息(如 websockets 文档中的示例“聊天”程序),或者为单独的游戏线程对传入消息进行排队流程。
关于haskell - 无法将多个客户端与 Haskell Websocket 服务器一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61091008/