【问题标题】:PipeWriter and length prefixed messagesPipeWriter 和长度前缀消息
【发布时间】:2021-07-12 07:07:04
【问题描述】:

我正在尝试使用带有字节长度前缀的PipeWriter 编写二进制消息。 在整个消息完成之前,我不知道字节长度。 PipeWriter 可以做到这一点吗?

基本上我正在尝试实现这三种方法:

void StartMessage(PipeWriter writer)
{
    // leave 4 empty bytes for length written at later time
    this.header_ = writer.GetMemory(4);
    
    writer.Advance(4);
}

void Write(PipeWriter writer, ReadOnlySpan<byte> span)
{
    var buffer = writer.GetSpan(span.Length);

    span.CopyTo(buffer);

    writer.Advance(span.Length);

    this.totalLength_ += span.Length;
}

ValueTask EndMessage(PipeWriter writer)
{
    // should prepend this.totalLength_ to the message
    BinaryPrimities.WriteUInt32BingEndian(this.header_.Span, this.totalLength_);

    // signal end of message
    return writer.FlushAsync();
}

这给了我预期的结果,但PipeWrite.Advance 的文档指出:

调用 System.IO.Pipelines.PipeWriter.Advance(System.Int32) 后必须请求新的缓冲区才能继续写入更多数据;您无法写入先前获取的缓冲区。

使用PipeReaderAdvanceTo(consumed,examined) 方法可以轻松读取此类消息,其中我们仅在整个消息长度可用时才使用输入,但我无法提出正确的PipeWriter 用法根据文档。

【问题讨论】:

标签: c# system.io.pipelines


【解决方案1】:

您所展示的模式将导致释放后使用。你会在随机部分覆盖你的输出缓冲区。

在所有字节都存在之前,您不需要发送消息,这意味着您需要所有消息都在内存中才能发送。

您可以通过写入 MemoryStream 轻松实现此目的,然后稍后将底层缓冲区传递给 PipeWriter。

另外,请注意 PipeWriter.GetMemory 可以并且将返回比您要求的更多的字节。

【讨论】:

    猜你喜欢
    • 2012-07-23
    • 2019-11-04
    • 2019-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-18
    • 1970-01-01
    • 2021-11-11
    相关资源
    最近更新 更多