如何让 C# WebSocketClient 持续监听消息

Nic*_*ick 3 c# unity-game-engine websocket

我正在编写一个程序(实际上是 Unity 中的一个游戏),它应该充当单独启动和运行的 Websocket 服务器的客户端。

我正在使用System.Net.Websockets ClientWebSocket. 我已经打开了连接,我可以发送消息,但与 Javascript 客户端不同的是,我会设置一个回调函数,每次 websocket 客户端收到消息时都会运行该函数,我很难理解 C# 的预期流程API。

这是我编写的消息处理程序:

public async Task HandleMessages() {
        using (var ms = new MemoryStream()) {
            var messageBuffer = WebSocket.CreateClientBuffer(8192, 8192);
            WebSocketReceiveResult result;
            do {
                result = await ws.ReceiveAsync(messageBuffer, CancellationToken.None);
                ms.Write(messageBuffer.Array, messageBuffer.Offset, result.Count);
            }
            while (!result.EndOfMessage);

            if (result.MessageType == WebSocketMessageType.Text) {
                var msgString = Encoding.UTF8.GetString(ms.ToArray());
                Debug.Log(msgString);
                var message = JsonConvert.DeserializeObject<Dictionary<String, String>>(msgString);
                if (message["roomCode"] == RoomCode.ToLower()) {
                    // Message was intended for us!
                    Debug.Log("[WS] Got a message of type " + message["messageType"]);
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

因此,在最初打开 Websocket 连接后,如果我这样调用:

await Task.WhenAll(HandleMessages());
Run Code Online (Sandbox Code Playgroud)

那么它将处理第一条传入消息,但不会处理任何后续消息。我尝试了很多不同的方法,但我不知道如何在每次收到消息时运行此任务。

有人对此事有任何见解吗?

Nic*_*ick 10

事实证明,与往常一样,这种情况下存在很大的用户错误因素。

我不理解 websocket 的一些基本概念,所以当我认为我正在从服务器广播消息时,我实际上只是将它们发送给某些客户端。经过 Marc Gravell 建议的改进以及更多时间的修改,我的 C# 客户端代码现在看起来像这样:

public async Task HandleMessages() {
        try {
            using (var ms = new MemoryStream()) {
                while (ws.State == WebSocketState.Open) {
                    WebSocketReceiveResult result;
                    do {
                        var messageBuffer = WebSocket.CreateClientBuffer(1024, 16);
                        result = await ws.ReceiveAsync(messageBuffer, CancellationToken.None);
                        ms.Write(messageBuffer.Array, messageBuffer.Offset, result.Count);
                    }
                    while (!result.EndOfMessage);

                    if (result.MessageType == WebSocketMessageType.Text) {
                        var msgString = Encoding.UTF8.GetString(ms.ToArray());
                        var message = JsonConvert.DeserializeObject<Dictionary<String, String>>(msgString);
                        if (message["roomCode"].ToLower() == RoomCode.ToLower()) {
                            Debug.Log("[WS] Got a message of type " + message["messageType"]);
                            // Message was intended for us!
                            switch (message["messageType"]) {
                                // handle messages here, unimportant to stackoverflow
                            }
                        }
                    }
                    ms.Seek(0, SeekOrigin.Begin);
                    ms.Position = 0;
                }
            }
        } catch (InvalidOperationException) {
            Debug.Log("[WS] Tried to receive message while already reading one.");
        }
    }
Run Code Online (Sandbox Code Playgroud)

一旦我将服务器配置为实际广播我认为正在广播的消息(迭代所有客户端并发送消息),它现在将读取多条消息。再次感谢您的帮助,希望这能帮助其他刚接触 websocket 的人有一些需要检查的东西