你的位置:首页 > ASP.net教程

[ASP.net教程]使用命名管道实现进程间通信

创建命名管道

命名管道常常用于应用程序之间的通迅,由于不需要进行序列化和反序列化操作,效率是非常高的。相比TCP通信方式,效率更高,但比共享内存要低点。
命名管道可以在本地机器或者局域网内机器实现进程间通信,所以是最佳的通信方式。

创建一个NamedPipeServerStream:

NamedPipeServerStream pipeServer = new NamedPipeServerStream(_pipName, PipeDirection.InOut, 10);

这里表示命名管道服务器的管道放心为双向通信,类似于TCP双工。接着,使用下面的代码等待连接:

pipeServer.WaitForConnection();

如果有连接,就可以使用流阅读器进行阅读:

 StreamReader sr = new StreamReader(pipeServer);

同样,也可以使用流写操作器,将数据写入流,管道的另一端,可以读取这个流:

 using (StreamWriter sw = new StreamWriter(pipeServer)) {    sw.AutoFlush = true;    sw.WriteLine("hello world " + str); }

注意:此处使用了using,意味着写完就会关闭流,但同时也会关闭管道,所以需要注意。假如客户端要读取全部数据,那么需要等到这里关闭流。

自定义应用层通信协议

如何读取管道的全部数据,看下面的代码:

 StreamReader sr = new StreamReader(pipeServer); string text =sr.ReadToEnd();

这种方式可以读取全部数据,但是,在管道的另外一段,如果留写操作器不调用 Close方法,这里没法读取完成,程序会阻塞在这里。 所以,必须定义一个“应用协议”,客户端告诉服务端合适结束读取数据。

我们仿照HTTP协议的方法,使用连续的2个以上的回车换行表示HTTP头信息结束,我们也这样定义,并附加其它标记来表示流数据发送完毕,参考发送端:

 public string Query(string request)    {      if (!_pipeClient.IsConnected)      {        _pipeClient.Connect(10000);      }      StreamWriter sw = new StreamWriter(_pipeClient);      sw.WriteLine(request);      sw.WriteLine();//连续2个换行外加"#END"表示结束      sw.WriteLine();      sw.WriteLine("#END");      sw.Flush();      StreamReader sr = new StreamReader(_pipeClient);      string returnVal = sr.ReadToEnd();      return returnVal;    }

而在服务端,采用下面的方式完成流数据的读取:

string str = null; string strAll = null; System.Text.StringBuilder sb = new System.Text.StringBuilder(); StreamReader sr = new StreamReader(pipeServer); while (pipeServer.CanRead && (null != (str = sr.ReadLine()))) {     //当遇到连续2个换行外加#END,表示输入结束   if (str == "#END" )   {     strAll = sb.ToString();     if (strAll.EndsWith("\r\n\r\n"))       break;   }   else   {     if (str == "")       sb.AppendLine();     else       sb.AppendLine(str);   } } strAll = strAll.Substring(0, strAll.Length - "\r\n\r\n\r\n".Length);

测试和下载

最后,写个客户端和服务端控制台程序:

namespace NamePipedSample_Server{  class Program  {    static void Main(string[] args)    {      NamedPipeListenServer svr = new NamedPipeListenServer("test");      svr.Run();      Console.Read();    }  }}

namespace NamePipedSample_Client{  class Program  {    static void Main(string[] args)    {      string sendStr = null;      using (NamedPipeClient client = new NamedPipeClient(".", "test"))      {        sendStr = "fff\r\ndddd\r\n";        Console.WriteLine("send:{0}",sendStr);        Console.WriteLine("Reply:{0}",client.Query(sendStr));        sendStr = "54353";        Console.WriteLine("send:{0}", sendStr);        Console.WriteLine("Reply:{0}", client.Query(sendStr));        sendStr = "aaaaaaa";        Console.WriteLine("send:{0}", sendStr);        Console.WriteLine("Reply:{0}", client.Query(sendStr));      }      Console.WriteLine("send all ok.");      Console.Read();    }  }}

 

经过测试,这种方法是先命名管道客户端-服务器通信成功。 本文程序是在网友原来文章的基础上改进的,在此表示感谢,原文地址:  http://blog.csdn.net/educast/article/details/7219774

本文程序Demo下载