Невозможно использовать несколько клиентов с сервером Haskell Websocket - PullRequest
3 голосов
/ 08 апреля 2020

Я пытаюсь протестировать свой игровой сервер с помощью веб-сокетов, но у меня проблемы с использованием нескольких клиентов. Подключение каждого из них работает нормально, но когда я запускаю игру и отправляю первые сообщения через сокеты, они выдают ошибку «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 кодом?

библиотека веб-сокетов

векторного размера

1 Ответ

4 голосов
/ 08 апреля 2020

См. Документацию для ServerApp типа . Как только действие IO завершается, базовый сокет закрывается. Итак, каждый из ваших первых трех клиентов принимает соединение, сохраняет соединение в state, а затем завершает работу, закрывая соединение. Только четвертый клиент сохраняет свое соединение открытым, и он не может делать ничего полезного с остальными тремя соединениями, которые теперь закрыты.

Если вы заменили последнюю строку на:

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

тогда это, вероятно, соединит всех четырех клиентов.

Чтобы исправить это «по-настоящему», вы можете заставить первые три соединения ждать вечно, а затем организовать четвертый поток, чтобы убить их, когда игра закончится. .

Однако я не уверен, что это правильная архитектура. Вместо того, чтобы только четвертый поток соединений работал и опрашивал все четыре соединения, вы, вероятно, захотите, чтобы каждый поток соединений вводил al oop для обработки входящих сообщений от своего клиента. Эти потоки могут изменять общее игровое состояние и / или напрямую транслировать сообщения другому клиенту (например, пример программы "chat" в документации websockets) или помещать в очередь входящие сообщения для обработки отдельного потока игры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...