如何将 websocket 连接解码为 json 流? [英] How to decode websocket connect as a json stream?

查看:38
本文介绍了如何将 websocket 连接解码为 json 流?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的客户端正在连接到 websocket 服务器,并且通信都是 json 格式.我使用 ClientWebSocket 及其 ReceiveAsync 方法如文档所述.我的阅读循环是这样的:

My client is connecting to a websocket server and the communications are all in json format. I use the ClientWebSocket and its ReceiveAsync method as documented. My read loop is something like this:

byte[] data = new byte[4096];
ArraySegment<byte> buffer = new ArraySegment<byte>(data);
readLoopTask = Task.Run(async () =>
{
    while (true)
    {
        var result = await socket.ReceiveAsync(buffer, CancellationToken.None);
        if (result.Count > 0)
        {
            string m = Encoding.ASCII.GetString(data, 0, result.Count);
            ProcessMessage(m); // decode json string
        }
        else
        {
            Console.WriteLine("recved zero:", result);
            break;
        }
    }
}, token);

我在这个实现中发现的问题是,服务器传递的一些 json 对象非常大,无法放入缓冲区,在这种情况下,读取的输入被截断并且不是有效的 json 字符串,因此解码失败.

The problems I found with this implementation is that some json objects the server passed is very big and it won't fit into the buffer, in that case the read input is truncated and is not a valid json string, so the decode fails.

有人可能会争辩说我可以继续读取 websocket 直到读取完整的 json 对象,但这会导致一个非常复杂的解决方案并且需要手动处理 json 字符串,因为我将不得不检查每个字节并搜索结尾json 字符串.我还需要保留之后的部分,因为它是下一个 json 对象的开始部分.

One could argue that I could continue reading the websocket until a complete json object is read, but that would result a very complex solution and requires handling of json string manually because I will have to check each byte and search for the end of json string. I will also need to preserve the part after that because it is the beginning part of next json object.

我的问题是为什么 WebSocket 没有将其网络流导出给用户,就像 TcpClient.GetStream 确实如此,在 TcpClient 的情况下,处理这种情况会很容易在某些情况下,只需将流提供给 json 解码器:

My question is that why WebSocket does not have its network stream exported to users, just like what TcpClient.GetStream does, in the TcpClient case, it will be very easy to handle this kind of situation, just supply the stream to a json decoder:

Stream stream = tcpClient.GetStream();
JsonDecoder decoder = new JsonDecoder(stream);
Object obj;
while (true) {
    decoder.Decode(obj);
    // handle obj
}

鉴于目前还没有这样的 API,那么有没有更好的方法来解决这个问题?

So is there better way to solve this problem given that such a API is not available currently?

推荐答案

好吧,终于发现这不是一个需要担心的问题.关键是ClientWebSocket.ReceiveAsync会返回一个WebSocketReceiveResult,里面有EndOfMessage,是一个布尔标志,表示这部分数据是否为一条消息的结尾,所以通常的操作是连续接收直到标志为真,然后将所有累积的数据馈入json解码器.

Ok, finally found this is not a question to worry about. The key is ClientWebSocket.ReceiveAsync will return a WebSocketReceiveResult, which has EndOfMessage, it is a Boolean flag to indicate whether this part of data is the end of a message, so the usual operation is receive continuously until the flag is true, then feed all the accumulated data into json decoder.

WebSocketReceiveResult result = null;
while(running) {
    do {
        result = await socket.ReceiveAsync(buffer, cts.Token).ConfigureAwait(false);
        if (result.Count > 0)
        {
             memStream.Write(buffer.Array, buffer.Offset, result.Count);
        }
        else
        {
             logger.LogWarning("WS recved zero: {0}, {1}", result.Count, socket.State);
             break;
        }
    } while (!result.EndOfMessage); // check end of message mark
}

这篇关于如何将 websocket 连接解码为 json 流?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆