C# 如果读取的字节太多,则会引发命名管道

C# 如果读取的字节太多,则会引发命名管道,c#,stream,named-pipes,C#,Stream,Named Pipes,我一直在使用命名管道进行进程间通信。到目前为止,只要消息的长度不超过管道缓冲区(1024字节),就可以正常工作 事实上,我认为任何管道都能够知道它包含的当前数据长度。很明显,这只是看起来的。这很好,但是当您读取太多字节时,为什么NamedPipeClientStream会引发ArgumentException呢 如果流没有长度属性(抛出NotImplementedException),我如何知道可以读取多少字节 这是我的客户端代码。它应该类似于流上的任何其他缓冲读取操作: // Create m

我一直在使用命名管道进行进程间通信。到目前为止,只要消息的长度不超过管道缓冲区(1024字节),就可以正常工作

事实上,我认为任何管道都能够知道它包含的当前数据长度。很明显,这只是看起来的。这很好,但是当您读取太多字节时,为什么NamedPipeClientStream会引发ArgumentException呢

如果流没有长度属性(抛出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字节的消息。但有些更长(记录消息)


如何处理此问题?

您的管道是用
管道类型\消息打开的,而不是用
管道类型\字节打开的。
这就是为什么如果您没有阅读完整消息,代码将抛出。(您的读取模式是
管道\读取模式\消息

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

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

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

如果您无法为消息大小找到一个好的上限,那么另一种方法是定义一个协议。这可以简单到:

<messageLength:uint32><message data>

您的管道是用
管道类型\消息打开的,而不是用
管道类型\字节打开的。
这就是为什么如果您没有阅读完整消息,代码将抛出。(您的读取模式是
管道\读取模式\消息

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

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

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

如果您无法为消息大小找到一个好的上限,那么另一种方法是定义一个协议。这可以简单到:

<messageLength:uint32><message data>

您的管道是用
管道类型\消息打开的,而不是用
管道类型\字节打开的。
这就是为什么如果您没有阅读完整消息,代码将抛出。(您的读取模式是
管道\读取模式\消息

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

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

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

如果您无法为消息大小找到一个好的上限,那么另一种方法是定义一个协议。这可以简单到:

<messageLength:uint32><message data>

您的管道是用
管道类型\消息打开的,而不是用
管道类型\字节打开的。
这就是为什么如果您没有阅读完整消息,代码将抛出。(您的读取模式是
管道\读取模式\消息

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

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

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

如果您无法为消息大小找到一个好的上限,那么另一种方法是定义一个协议。这可以简单到:

<messageLength:uint32><message data>


实际上我使用的是基于字节的消息模式。我一直在使用byte,因为我需要传递各种数据(各种基本数据类型),这在字节形式下效果最好。这就是PipeMessage的基本功能,它是一个允许以字节[]形式写入和读取数据的类,反之亦然。但还是不行。因为我有时会通过消息传递异常,所以我永远不知道消息的实际长度(字符串是不确定的)。@SharpShade扩展了我的答案。好吧,现在这很尴尬。我使用第一个字节作为消息标识符,但我还没有想到使用第二个字节作为消息长度。。。有时你真的会因为树而错过森林。事实上,我使用的是基于字节的消息模式。我一直在使用byte,因为我需要传递各种数据(各种基本数据类型),这在字节形式下效果最好。这就是PipeMessage的基本功能,它是一个允许以字节[]形式写入和读取数据的类,反之亦然。但还是不行。因为我有时会通过消息传递异常,所以我永远不知道消息的实际长度(字符串是不确定的)。@SharpShade扩展了我的答案。好吧,现在这很尴尬。我使用第一个字节作为消息标识符,但我还没有想到使用第二个字节作为消息长度。。。有时你真的会因为树而错过森林。事实上,我使用的是基于字节的消息模式。我一直在使用byte,因为我需要传递各种数据(各种基本数据类型