net 命名管道 NamedPipe 的使用

命名管道常常用于应用程序之间的通迅,由于不需要进行序列化和反序列化操作,效率还是非常高的。我们今天做个演示看看。

类似于TCP/IP的模式的c/s结构。我们先建立一个服务器端:

 

            using  (NamedPipeServerStream pipeServer  =
                
new  NamedPipeServerStream( " testpipe " , PipeDirection.Out))//创建连接
            {
                pipeServer.WaitForConnection();//等待连接,程序会阻塞在此处,直到有一个连接到达

                
try
                {
                    
//  Read user input and send that to the client process.
                     using  (StreamWriter sw  =   new  StreamWriter(pipeServer))
                    {
                        sw.AutoFlush 
=   true ;
                        sw.WriteLine(
" hello world  " );
                    }
                }
                
//  Catch the IOException that is raised if the pipe is broken
                
//  or disconnected.
                 catch  (IOException e)
                {
                    Console.WriteLine(
" ERROR: {0} " , e.Message);
                }
            }

上面的代码很简单,构建NamedPipeServerStream对象,然后调用该对象的WaitForConnection方法等待客户端的连接,一旦连接建立,向客户端写入一个字符串“hello world 

 

下面写一个客户端。

             using  (NamedPipeClientStream pipeClient  =
                        
new  NamedPipeClientStream( " . " " testpipe " , PipeDirection.In))
            {
                pipeClient.Connect();

                
using  (StreamReader sr  =   new  StreamReader(pipeClient))
                {
                    
string  temp;
                    
while  ((temp  =  sr.ReadLine())  !=   null )
                    {
                        MessageBox.Show(
string .Format( " Received from server: {0} " , temp));
                    }
                }
            }

 

 客户端构建了一个NamedPipeClientStream 对象,调用Connect方法建立连接,连接通畅后,立即从通道里读取数据,这里会读取到"hello world "字符。

 

本文结束。太简单了吧。微软都把这些类库封装的很方便了。

---------------------

以下是扩充内容。

既然 命名管道 给我们提供一种通讯方式,那么我们尝试使用这个通讯做个 C/S 结构的消息监听演示。我们利用 命名管道 封装两个类,一个服务类,一个客户机类。使得我们在使用的时候无需考虑通讯的底层实现。

那么我们先看下服务端的类:

 

/*  ----------------------------------------------------------
* @名称    :    
* @描述    :    
* @创建人  :    张云飞
* @创建日期:    2011/7/12 9:57:55
* @修改记录:
* ----------------------------------------------------------
*/


using  System;
using  System.Collections.Generic;
using  System.ComponentModel;
using  System.Data;
using  System.IO.Pipes;
using  System.IO;
using  System.Threading;

namespace  SimpleCode.NamedPipeLib
{
    
public   class  NamedPipeListenServer
    {
        List
< NamedPipeServerStream >  _serverPool  =   new  List < NamedPipeServerStream > ();
        
string  _pipName  =   " test " ;
        
public  NamedPipeListenServer( string  pipName)
        {
            _pipName 
=  pipName;
        }

        
///   <summary>
        
///  创建一个NamedPipeServerStream
        
///   </summary>
        
///   <returns></returns>
         protected  NamedPipeServerStream CreateNamedPipeServerStream()
        {
            NamedPipeServerStream npss 
=   new  NamedPipeServerStream(_pipName, PipeDirection.InOut,  10 );
            _serverPool.Add(npss);
            Console.WriteLine(
" 启动了一个NamedPipeServerStream  "   +  npss.GetHashCode());
            
return  npss;
        }

        
///   <summary>
        
///  销毁
        
///   </summary>
        
///   <param name="npss"></param>
         protected   void  DistroyObject(NamedPipeServerStream npss)
        {
            npss.Close();
            
if  (_serverPool.Contains(npss))
            {
                _serverPool.Remove(npss);
            }
            Console.WriteLine(
" 销毁一个NamedPipeServerStream  "   +  npss.GetHashCode());
        }

        
public   void  Run()
        {
            
using  (NamedPipeServerStream pipeServer  =  CreateNamedPipeServerStream())
            {
                pipeServer.WaitForConnection();
                Console.WriteLine(
" 建立一个连接  "   +  pipeServer.GetHashCode());

                Action act 
=   new  Action(Run);
                act.BeginInvoke(
null null );

                
try
                {
                    
bool  isRun  =   true ;
                    
while  (isRun)
                    {
                        
string  str  =   null ;
                        StreamReader sr 
=   new  StreamReader(pipeServer);
                        
while  (pipeServer.CanRead  &&  ( null   !=  (str  =  sr.ReadLine())))
                        {
                            ProcessMessage(str, pipeServer);

                            
if  ( ! pipeServer.IsConnected)
                            {
                                isRun 
=   false ;
                                
break ;
                            }
                        }

                        Thread.Sleep(
50 );
                    }
                }
                
//  Catch the IOException that is raised if the pipe is broken
                
//  or disconnected.
                 catch  (IOException e)
                {
                    Console.WriteLine(
" ERROR: {0} " , e.Message);
                }
                
finally
                {
                    DistroyObject(pipeServer);
                }
            }

        }

        
///   <summary>
        
///  处理消息
        
///   </summary>
        
///   <param name="str"></param>
        
///   <param name="pipeServer"></param>
         protected   virtual   void  ProcessMessage( string  str, NamedPipeServerStream pipeServer)
        {
            
//  Read user input and send that to the client process.
             using  (StreamWriter sw  =   new  StreamWriter(pipeServer))
            {
                sw.AutoFlush 
=   true ;
                sw.WriteLine(
" hello world  "   +  str);
            }
        }

        
///   <summary>
        
///  停止
        
///   </summary>
         public   void  Stop()
        {
            
for  ( int  i  =   0 ; i  <  _serverPool.Count; i ++ )
            {
                var item 
=  _serverPool[i];

                DistroyObject(item);
            }
        }
    }
}

我们使用 List<NamedPipeServerStream> _serverPool 做为一个集合容器,记录和保存所有的建立的连接。在Run方法里创建新的 命名管道连接 的实例。注意我们这里使用了一个异步委托。

                Action act = new Action(Run);
                act.BeginInvoke(
nullnull);
在一个Run方法执行时,异步执行了另一个Run方法,在这个Run方法的实现了阻塞监听,也就是一个新的连接建立后,立即建立一个新的监听连接,使得在处理一个连接的数据时,也可以等待新的客户端连接进入。

Stop方法会遍历所有的连接,保证销毁所有的连接。 ProcessMessage方法是处理客户机发来的消息,我们这里使用了ReadLine方法,也就是我们认为一行作为一个消息的单元。注意这个方法是virtual的,我们可以实现它的重载,以增加新的消息处理方式。

 

下面是客户端的封装类:

 

/*  ----------------------------------------------------------
* @名称    :    
* @描述    :    
* @创建人  :    张云飞
* @创建日期:    2011/7/12 11:31:30
* @修改记录:
* ----------------------------------------------------------
*/

using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.IO.Pipes;
using  System.IO;

namespace  SimpleCode.NamedPipeLib
{
    
public   class  NamedPipeClient : IDisposable
    {
        
string  _serverName;
        
string  _pipName;
        NamedPipeClientStream _pipeClient;

        
///   <summary>
        
///  
        
///   </summary>
        
///   <param name="serverName"> 服务器地址 </param>
        
///   <param name="pipName"> 管道名称 </param>
         public  NamedPipeClient( string  serverName,  string  pipName)
        {
            _serverName 
=  serverName;
            _pipName 
=  pipName;

            _pipeClient 
=   new  NamedPipeClientStream(serverName, pipName, PipeDirection.InOut);

        }

        
///   <summary>
        
///  查询
        
///   </summary>
        
///   <param name="request"></param>
        
///   <returns></returns>
         public   string  Query( string  request)
        {
            
if  ( ! _pipeClient.IsConnected)
            {
                _pipeClient.Connect(
10000 );
            }

            StreamWriter sw 
=   new  StreamWriter(_pipeClient);
            sw.WriteLine(request);
            sw.Flush();

            StreamReader sr 
=   new  StreamReader(_pipeClient);
            
string  temp;
            
string  returnVal  =   "" ;
            
while  ((temp  =  sr.ReadLine())  !=   null )
            {
                returnVal 
=  temp;
                
// nothing
            }
            
return  returnVal;
        }

        
#region  IDisposable 成员

        
bool  _disposed  =   false ;
        
public   void  Dispose()
        {
            
if  ( ! _disposed  &&  _pipeClient  !=   null )
            {
                _pipeClient.Dispose();
                _disposed 
=   true ;
            }
        }

        
#endregion
    }
}

这个类需要注意的是,在构造里构造类命名管道的对象。有意思的地方是Query方法,该方法会接受一个string参数,并且返回一个string对象,实际会将输入参数的内容发送往服务端,将服务端的处理结果做为该方法的返回值。

 

服务端使用演示:

            NamedPipeListenServer svr  =   new  NamedPipeListenServer( " test " );
            svr.Run();

客户端使用演示:

             using  (NamedPipeClient client  =   new  NamedPipeClient( " . " , " test " ))
            {
                MessageBox.Show( client.Query(
" fff " ));
                MessageBox.Show(client.Query(
" 54353 " ));
            }

 

呵呵,使用起来更简单和方便了。而且完全不用考虑内部的命名管道连接。

本文完。

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net

猜你喜欢

转载自www.cnblogs.com/sjwudhwhhw/p/10442758.html
今日推荐