如何让 C# WebSocketClient 持续监听消息
Posted
技术标签:
【中文标题】如何让 C# WebSocketClient 持续监听消息【英文标题】:How to get C# WebSocketClient to listen for messages in an ongoing capacity 【发布时间】:2020-02-14 04:34:11 【问题描述】:我正在编写一个程序(实际上是 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"]);
所以在最初打开我的 Websocket 连接后,如果我这样调用:
await Task.WhenAll(HandleMessages());
然后它将处理第一条传入消息,但不处理任何后续消息。我尝试了很多不同的方法,但我不知道如何在每次收到消息时运行此任务。
有人对此事有任何见解吗?
【问题讨论】:
我没有使用 websockets 的经验,但我认为result.EndOfMessage
表示何时收到完整的消息,而不是表示没有更多数据的潜力。
是的,表示该消息的结束。然而,另一条消息(实际上更多)将被发送,我需要在它们进来时处理它们
再次调用await ws.ReceiveAsync(...
不起作用吗?
它会,但 websocket 的重点是在发送消息时接收消息。每当从 websocket 服务器广播消息时,如何让整个处理程序作为回调函数(或 C#ey 等效概念)运行
它似乎在这里你只需要一个while
循环? (大概在ms
范围内,只需确保在循环结束时将Length
和Position
设置为零)
【参考方案1】:
事实证明,在这种情况下,与往常一样,存在很好的用户错误因素。
我不了解 websockets 的一些基本概念,所以当我认为我正在从我的服务器广播消息时,我实际上只是将它们发送到某些客户端。随着 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 ***
ms.Seek(0, SeekOrigin.Begin);
ms.Position = 0;
catch (InvalidOperationException)
Debug.Log("[WS] Tried to receive message while already reading one.");
一旦我将服务器配置为实际广播我认为我正在广播的消息(遍历所有客户端并发送消息),它现在将读取多条消息。再次感谢您的帮助,希望这将有助于将来其他刚接触 websockets 的人有需要检查的东西
【讨论】:
以上是关于如何让 C# WebSocketClient 持续监听消息的主要内容,如果未能解决你的问题,请参考以下文章
如何使用带有 SSL 的 Spring WebSocketClient?
使用 tech.gusavila92.websocketclient.WebSocketClient 时出现证书错误
org.java_websocket.client.WebSocketClient.run 处的 java.lang.AssertionError(WebSocketClient.java:190)