首页 > 解决方案 > 从字节数组中解码分隔帧

问题描述

我有由字节分隔的帧来启动和停止帧(它们不会出现在流中)。

我从磁盘或网络套接字读取了一个块,然后我需要传递给一个解串器,但只有在我首先对数据包进行解帧之后。

帧可能跨越多个已读取的块,请注意第 3 帧是如何拆分到array 1array 2的。

与其为这个常见问题重新发明轮子,是否存在任何 github 或类似项目?

我正在ReadOnlySequenceSegment<T>https://www.codemag.com/article/1807051/Introducing-.NET-Core-2.1-Flagship-Types-Span-T-and-Memory-T进行调查,并将在制定要求时发布更新.

框架

更新

除了 Stephen Cleary 链接(谢谢!!)到https://github.com/davidfowl/TcpEcho/blob/master/src/Server/Program.cs我有以下内容。

我的数据是 json,因此与原始问题不同,分隔符标记出现在流中。因此,我必须计算数组分隔符,并且只有在找到最外层[]字符时才声明一个框架。

下面的代码有效,并且完成的手动副本更少(不确定是否仍然在幕后完成 - 使用 David Fowl 方法的代码非常整洁)。

但是,我正在转换为数组而不是使用,buffer.PositionOf((byte)'[')因为我无法看到如何在PositionOf应用了偏移量的情况下调用 (即更深入地扫描过去找到的分隔符标记的帧)。

我是否以蛮力的方式使用/屠宰图书馆,或者下面的阵列是否适合使用?

class Program
{
    static async Task Main(string[] args)
    {
        using var stream = File.Open(args[0], FileMode.Open);
        var reader = PipeReader.Create(stream);

        while (true)
        {
            ReadResult result = await reader.ReadAsync();
            ReadOnlySequence<byte> buffer = result.Buffer;

            while (TryDeframe(ref buffer, out ReadOnlySequence<byte> line))
            {
                // Process the line.
                var str = System.Text.Encoding.UTF8.GetString(line.ToArray());
                Console.WriteLine(str);
            }

            // Tell the PipeReader how much of the buffer has been consumed.
            reader.AdvanceTo(buffer.Start, buffer.End);

            // Stop reading if there's no more data coming.
            if (result.IsCompleted)
            {
                break;
            }
        }

        // Mark the PipeReader as complete.
        await reader.CompleteAsync();     
    }

    private static bool TryDeframe(ref ReadOnlySequence<byte> buffer, out ReadOnlySequence<byte> frame)
    {
        int frameCount = 0;
        int start = -1;
        int end = -1;

        var bytes = buffer.ToArray();

        for (var i = 0; i < bytes.Length; i++)
        {
            var b = bytes[i];

            if (b == (byte)'[')
            {
                if (start == -1)
                    start = i;

                frameCount++;
            }
            else if (b == (byte)']')
            {
                frameCount--;

                if (frameCount == 0)
                {
                    end = i;
                    break;
                }
            }
        }

        if (start == -1 || end == -1) // no frame found
        {
            frame = default;
            return false; 
        }

        frame = buffer.Slice(start, end+1);
        buffer = buffer.Slice(frame.Length);
        return true;
    }
}

标签: sockets.net-core

解决方案


是否存在任何 github 或类似项目?

David Fowler 有一个回显服务器,它使用管道来实现分隔帧。


推荐阅读