命名管道跨进程通信实例1(转)

原文地址:http://www.cnblogs.com/yukaizhao/archive/2011/08/08/namedpipeserverstream-example.html

本文介绍命名管道使用实例,文中例子是几个客户端都通过一台服务器获得新生成的int类型id。

服务器端功能:当客户端请求一个新的id时,将现有id自增1,然后返回给客户端。

服务器端实现:在程序启动时,启动n个线程,在每个线程中都声明一个NamedPipeServerStream的实例,并循环的WaitForConnection(),将新的id写入到命名管道中,然后断开连接。在程序退出时释放NamedPipeServerStream实例

服务器端代码:

class Program
{
    //命名管道名字
    private const string PIPE_NAME = "testpipe";
    //定义线程数,也是NamedPipeServerStream的允许最多的实例数
    private const int MAX_THREAD_COUNT = 3;

    private static volatile int _runingThreadCount = 0;
    private static volatile int _newID = 0;

    private static NamedPipeServerStream[] _serverStreams;

    static void Main(string[] args)
    {
        _serverStreams = new NamedPipeServerStream[MAX_THREAD_COUNT];
        //在进程退出时,释放所有NamedPipeServerStream实例
        AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
        //启动线程
        StartServers();
        Console.Read();
    }
    /// <summary>
    /// 进程退出时释放命名管道
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    static void CurrentDomain_ProcessExit(object sender, EventArgs e)
    {
        if (_serverStreams != null)
        {
            foreach (NamedPipeServerStream item in _serverStreams)
            {
                item.Dispose();
            }
        }
    }
    /// <summary>
    /// 启动线程
    /// </summary>
    private static void StartServers()
    {
        for (int i = 0; i < MAX_THREAD_COUNT; i++)
        {
            Thread thread = new Thread(new ThreadStart(StartNewIDServer));
            thread.Start();
        }
    }
    /// <summary>
    /// 启动一个NamedPipeServerStream实例
    /// </summary>
    private static void StartNewIDServer()
    {
        NamedPipeServerStream stream = null;
        Console.WriteLine("start server in thread:" + Thread.CurrentThread.ManagedThreadId);

        stream = _serverStreams[_runingThreadCount] = new NamedPipeServerStream(PIPE_NAME,
            PipeDirection.InOut,
            MAX_THREAD_COUNT,
            PipeTransmissionMode.Message,
            PipeOptions.None);
        while (true)
        {
            stream.WaitForConnection();

            int newID = ++_newID;
            byte[] bytes = BitConverter.GetBytes(newID);
            stream.Write(bytes,0,bytes.Length);
            stream.Flush();
            Console.WriteLine("threadNo:"+Thread.CurrentThread.ManagedThreadId+"\r");
            stream.Disconnect();
        }
    }
}

客户端的功能是不断的发出获得新id的请求,并打印新id,在客户端可以配置服务端的服务器IP。

客户端代码:

class Program
{
    private const string PIPE_NAME = "testpipe";
    static void Main(string[] args)
    {
        Console.WriteLine("请输入任何字符回车开始执行程序...");
        Console.Read();
        do
        {
            //内网服务器IP,必须是局域网
            string serverName = "127.0.0.1";
            //声明NamedPipeClientStream实例
            using (NamedPipeClientStream clientStream=new NamedPipeClientStream(
                serverName,
                PIPE_NAME
                ))
            {
                //连接服务器
                clientStream.Connect(1000);
                //设置为消息读取模式
                clientStream.ReadMode = PipeTransmissionMode.Message;
                do
                {
                    byte[] bytes = new byte[4];
                    clientStream.Read(bytes,0,4);
                    int val = BitConverter.ToInt32(bytes,0);
                    Console.WriteLine("NewID=="+val+"\r");
                } while (!clientStream.IsMessageComplete);
            }
            Thread.Sleep(1);
        } while (true);
    }
}

在sql server中就使用了命名管道在局域网内挂进程通讯。

在声明NamedPipeServerStream实例是可以指定其实例个数,如果实例数超过这个数,就会抛出“所有管道范例都在使用中”的IO异常。

本例不可以在实际项目中使用。

程序源码下载

posted @ 2015-12-23 14:22  天马3798  阅读(907)  评论(0编辑  收藏  举报