命名管道的连接有两次阻塞的地方,一是在WaitForConnection()时[客户端进行连接同理]会阻塞,二是在ReadString()[读取管道信息]时。
在服务器端第一次创建命名管道后等待连接,当客户端连接成功后服务器端的命名管道就用作通讯用途。如果需要再次等待连接,服务器端就需要再次打开命名管道(创建一个命名管道的实例)并等待连接。
对于客户端每次打开命名管道后建立与服务器间的连接,然后就可以利用命名管道进行通信,如果需要建立第二个连接则需要再次打开管道和再次建立连接。
创建命名管道时需要指定一个主机名和管道名,在同一主机上管道名称是唯一的,一个命名管道一旦被创建就不允许相同名称的管道再被创建。
请注意关闭管道和关闭连接是不同的意思,在同一个管道上可以依次反复建立连接,而且可以减小系统的负荷。而且如果指定了管道最大数量限制那么在打开的管道达到最大限制后如果不关闭旧管道就无法打开新管道。 对于客户方则无法关闭连接,而只能直接调用Close()关闭管道。如果客户端调用了close()关闭了管道,那么再次连接服务器端的原管道就不可以了,服务端的管道也需要重新进行初始化并且等待连接。
关于双向通信:
上篇文章中提到了管道可以进行双向通信,双向通信实际上就是服务端模拟客户端回发消息,客户端进行接收的过程,主要是调用了pipeServer.RunAsClient(StartListening),StartListening是一个回调方法,里面可以写回发的消息。而客户端就进行Read就可以了,具体代码为:
客户端主要代码:
NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", _pipeName, PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.Impersonation);
pipeClient.Connect();
while (true)
{
//Write
string sRequest = "request";
StreamString ss = new StreamString(pipeClient);
ss.WriteString(sRequest);
//Read
string sResult = ss.ReadString();
if (sResult != "")
{
//
}
}
服务端主要代码:
NamedPipeServerStream pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.InOut, 1);
pipeServer.WaitForConnection();
try
{
_ss = new StreamString(pipeServer);
string sResult = _ss.ReadString();
if ( sResult != "")
{
pipeServer.RunAsClient(StartListening);
}
}
catch (IOException ex)
{
}
private void StartListening()
{
//Return result message
string sResult = "request";
_ss.WriteString(sResult);
}
因本人的程序包含一些复杂的逻辑处理,只是贴出来部分主干代码,代吗不能直接运行,希望博友理解含义后自行实践。