【问题标题】:Named Pipe throws if you read too many bytes如果读取太多字节,命名管道会抛出
【发布时间】:2015-04-22 03:01:51
【问题描述】:

我一直在使用命名管道进行进程间通信。到目前为止,只要消息不再作为管道缓冲区(1024 字节),这工作得很好。

我实际上认为任何管道都能够告诉它包含的当前数据长度。显然只能寻找。这很好,但是为什么读取太多字节时 NamedPipeClientStream 会抛出 ArgumentException 呢?

如果 Stream 没有 Length 属性(抛出 NotImplementedException),我应该如何知道可以读取多少字节?

这是我的客户端代码。它应该像对流的任何其他缓冲读取操作一样:

// Create message
PipeMessage message = PipeMessage.CreateIncomingMessage((byte) firstByte);

byte[] buffer = new byte[client.InBufferSize];
int bytesRead, offset = 0;
try
{
    while ((bytesRead = client.Read(buffer, offset, buffer.Length)) > 0)
    {
        message.Append(buffer, bytesRead);
        offset += bytesRead;
    }
}
catch (Exception ex)
{
    Log("[ERROR] Reading message failed: " + ex.Message + ex.StackTrace, _clientLogger);
}

如何读取超过输入缓冲区大小的消息?还是我需要浪费资源并设置一个非常大的缓冲区,只是因为?

我通常会收到不大于 ~50-500 字节的消息。但有些更长(记录消息)。

我该如何处理?

【问题讨论】:

    标签: c# stream named-pipes


    【解决方案1】:

    你的管道是用PIPE_TYPE_MESSAGE而不是PIPE_TYPE_BYTE打开的。 这就是如果您没有阅读完整消息,代码会抛出的原因。 (你的阅读模式是PIPE_READMODE_MESSAGE)。

    有关详细信息,请参阅CreateNamedPipe 文档。 基本上,如果对方写入大小为 N 的消息,您的读取必须提供大小为 N(或更大)的缓冲区。

    如果您不喜欢面向消息的样式,而是更喜欢将管道视为字节流(然后您必须对其进行解析),您可能希望找到一种方法来相应地配置管道。

    您与另一方代码的合同至少应由 1 个要求定义,例如最大消息长度 =

    如果您根本找不到适合您的消息大小的上限,那么另一种选择是定义一个协议。这可以很简单:

    <messageLength:uint32><message data>
    

    【讨论】:

    • 其实我使用的是基于字节的消息模式。我一直在使用字节,因为我需要传递各种数据(各种基本数据类型),这以字节的形式效果最好。这基本上就是 PipeMessage 所做的,它是一个允许以 byte[] 形式写入和读取数据的类,反之亦然。还是不行。因为我有时会通过消息传递异常,所以我永远不知道消息实际上会持续多长时间(字符串只是无法确定)。
    • @SharpShade 扩展了我的答案。
    • 嗯,现在很尴尬。我使用第一个字节作为消息标识符,但我还没有想出使用第二个字节作为消息长度的想法……有时你真的只见树木不见森林。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-25
    相关资源
    最近更新 更多