C# 命名管道流示例未显示结果
我是新来的管道流,并试图实践。我已经编写了以下两个项目,但是我看不到客户机项目的结果(我在服务器项目中编写)。这是第一个项目:C# 命名管道流示例未显示结果,c#,namedpipeserverstream,C#,Namedpipeserverstream,我是新来的管道流,并试图实践。我已经编写了以下两个项目,但是我看不到客户机项目的结果(我在服务器项目中编写)。这是第一个项目: using (NamedPipeServerStream namedPipeServer = new NamedPipeServerStream("test-pipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message)) { byte[] bytes = Encoding.Default.GetByte
using (NamedPipeServerStream namedPipeServer = new NamedPipeServerStream("test-pipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message))
{
byte[] bytes = Encoding.Default.GetBytes("Hello, it's me!\n");
namedPipeServer.WaitForConnection();
Console.WriteLine("A client has connected!");
namedPipeServer.Write(bytes, 0, bytes.Length);
}
这是第二个项目:
using (NamedPipeClientStream namedPipeClient = new NamedPipeClientStream(".", "test-pipe", PipeDirection.InOut))
{
namedPipeClient.Connect();
namedPipeClient.ReadMode = PipeTransmissionMode.Message;
string serverResponse = string.Empty;
byte[] readBytes = new byte[5];
while (!namedPipeClient.IsMessageComplete)
{
namedPipeClient.Read(readBytes, 0, readBytes.Length);
serverResponse = Encoding.Default.GetString(readBytes);
readBytes = new byte[5];
}
System.Console.WriteLine(serverResponse);
byte[] writeBytes = Encoding.Default.GetBytes("Hello from client!\n");
namedPipeClient.Write(writeBytes, 0, writeBytes.Length);
}
这个怎么了
感谢尝试使用
StreamReader
从两个管道读取消息。
服务器:
客户:
using (NamedPipeClientStream namedPipeClient = new NamedPipeClientStream(".", "test-pipe", PipeDirection.InOut))
{
namedPipeClient.Connect();
var reader = new StreamReader(namedPipeClient);
var msg = reader.ReadLine();
Console.WriteLine(msg);
byte[] writeBytes = Encoding.Default.GetBytes("Hello from client!\n");
namedPipeClient.Write(writeBytes, 0, writeBytes.Length);
namedPipeClient.WaitForPipeDrain();
}
客户端没有收到来自服务器的任何消息,因为在执行读取操作后必须调用
namedPipeClient.IsMessageComplete
。请参见文档中的:
获取一个值,该值指示消息中是否有更多数据
从最近的读取操作返回
否则,namedPipeClient.IsMessageComplete
返回true
和中的代码,而
-循环不执行。因此,您必须将while
循环重写为do-while
循环,以确保在测试namedPipeClient.IsMessageComplete
之前执行读取操作
但还有更多问题,请参见注释以了解解释:
using (NamedPipeClientStream namedPipeClient = new NamedPipeClientStream(".", "test-pipe", PipeDirection.InOut))
{
namedPipeClient.Connect();
namedPipeClient.ReadMode = PipeTransmissionMode.Message;
// StringBuilder is more efficient for string concatenation
StringBuilder serverResponse = new StringBuilder();
byte[] readBytes = new byte[5];
do
{
// You need to store number of bytes read from pipe (to readCount variable).
// It can be less then the length of readBytes buffer, in which case
// GetString() would decode characters beyond end of message.
var readCount = namedPipeClient.Read(readBytes, 0, readBytes.Length);
var readText = Encoding.Default.GetString(readBytes, 0, readCount);
// You original code "overwrites" content of serverResponse variable instead
// of concatenating it to the previous value. So you would receive only
// the last part of the server message.
serverResponse.Append(readText);
// It is not needed to create new buffer, you can just reuse existing buffer
//readBytes = new byte[5];
// IsMessageComplete is now tested after read operation
} while (!namedPipeClient.IsMessageComplete);
System.Console.WriteLine(serverResponse.ToString());
// You current server implementation exits as soon as it sends message to the client
// and does not wait for incomming message. You'll have to change server accordingly
// to be able to send a message back to the server.
//byte[] writeBytes = Encoding.Default.GetBytes("Hello from client!\n");
//namedPipeClient.Write(writeBytes, 0, writeBytes.Length);
}
编辑: 当命名管道处于
PipeTransmissionMode.Message
模式时,服务器上对NamedPipeServerStream.Write()
的每次调用都会将数据作为单独的消息通过管道发送。然后,客户端可以接收彼此分离的这些消息
(与PipeTransmissionMode.Byte
模式相反,在该模式下,无论服务器使用NamedPipeServerStream.Write()执行多少次写入操作,客户端都只接收单个连续的字节流)
当客户端从管道读取数据时(namedPipeClient.Read()
),允许方法返回较少的请求数据(例如,当接收缓冲区中没有足够的空间来存储整个消息,或者消息比请求的字节数短时),请参阅
返回读入缓冲区的字节总数这个
可能小于请求的字节数,如果
字节当前不可用,如果流的结尾不可用,则为0
达到
然后,您可以使用namedPipeClient.IsMessageComplete
和readCount
来检测此问题。让我用一些例子来解释它:假设服务器向客户机发送消息ABCDEFGHIJKL
,编码为字节数组{65、66、67、68、69、70、71、72、73、74、75、76}
。此消息的长度为12字节,因此它不适合5字节长的接收缓冲区(readBytes
)。因此,当客户端首次使用namedPipeClient.Read()
从管道中读取时,接收缓冲区将只包含消息的前5个字节({65、66、67、68、69}
,对应于ABCDE
)。这就是namedPipeClient.IsMessageComplete
将帮助我们的地方,因为它将返回false
,表明我们没有收到完整的消息,还有一些字节,我们应该继续读取
从管道中读取的第二个数据将类似,我们将读取消息的第二部分({70,71,72,73,74}
对应于FGHIJ
),namedPipeClient.IsMessageComplete
仍然是false
表示消息不完整
当第三次从管道完成读取时,将只读取剩余的2个字节({75,76}
,对应于KL
),但我们的缓冲区仍然有5个字节长,因此它看起来是这样的:({75,76,72,73,74}
对应于KLHIJ
)。值72、73、74仍然存在于循环的上一次迭代中。现在,将从namedPipeClient.Read()
返回的值存储到readCount
变量非常重要。它将包含值2,表明只有2字节的<代码> BytRead 缓冲区是有效的,其余字节应该被忽略。例如,“命名管道流失败”的标题,以及描述实际发生的情况和预期发生的情况的问题。希望这有帮助。@Richardisimo对不起,我不是来这里的。没问题,我只是想帮你。:)@如果IsMessageComplete做什么?我不太理解MSDN文档。另外,为什么我们需要使用readCount变量呢。它真正存储的是什么数据?顺便说一句,非常感谢much@Marc2001我给答案加了解释,老兄!你是我在网上遇到的最棒的人。非常感谢!你真的帮了我。
using (NamedPipeClientStream namedPipeClient = new NamedPipeClientStream(".", "test-pipe", PipeDirection.InOut))
{
namedPipeClient.Connect();
namedPipeClient.ReadMode = PipeTransmissionMode.Message;
// StringBuilder is more efficient for string concatenation
StringBuilder serverResponse = new StringBuilder();
byte[] readBytes = new byte[5];
do
{
// You need to store number of bytes read from pipe (to readCount variable).
// It can be less then the length of readBytes buffer, in which case
// GetString() would decode characters beyond end of message.
var readCount = namedPipeClient.Read(readBytes, 0, readBytes.Length);
var readText = Encoding.Default.GetString(readBytes, 0, readCount);
// You original code "overwrites" content of serverResponse variable instead
// of concatenating it to the previous value. So you would receive only
// the last part of the server message.
serverResponse.Append(readText);
// It is not needed to create new buffer, you can just reuse existing buffer
//readBytes = new byte[5];
// IsMessageComplete is now tested after read operation
} while (!namedPipeClient.IsMessageComplete);
System.Console.WriteLine(serverResponse.ToString());
// You current server implementation exits as soon as it sends message to the client
// and does not wait for incomming message. You'll have to change server accordingly
// to be able to send a message back to the server.
//byte[] writeBytes = Encoding.Default.GetBytes("Hello from client!\n");
//namedPipeClient.Write(writeBytes, 0, writeBytes.Length);
}