System.IO系列:局域网内多线程使用命名管道在进程之间通信实例

来源:互联网 发布:教学软件讲师宝好用吗 编辑:程序博客网 时间:2024/06/08 15:15
有关管道的基本用法请看System.IO之使用管道在进程间通信 (System.IO.Pipes使用)。
本文介绍命名管道使用实例,文中例子是几个客户端都通过一台服务器获得新生成的int类型id。
服务器端功能:当客户端请求一个新的id时,将现有id自增1,然后返回给客户端。
服务器端实现:在程序启动时,启动n个线程,在每个线程中都声明一个NamedPipeServerStream的实例,并循环的WaitForConnection(),将新的id写入到命名管道中,然后断开连接。在程序退出时释放NamedPipeServerStream实例
如下代码实现: 
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.IO;using System.IO.Pipes;using System.Threading;namespace IDServer{    class Program    {        /// <summary>        /// 命名管道名字        /// </summary>        private const string PIPE_NAME = "testNetworkPipe";        //定义线程数,也是NamedPipeServerStream的允许最多的实例数        private const int MAX_THREADS_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_THREADS_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_THREADS_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_THREADS_COUNT,                 PipeTransmissionMode.Message,                 PipeOptions.None);            int threadNo = _runingThreadCount;            _runingThreadCount += 1;            while (true)            {                stream.WaitForConnection();                int newId = ++_newId;                byte[] bytes = BitConverter.GetBytes(newId);                stream.Write(bytes, 0, bytes.Length);                stream.Flush();                Console.Write("threadNo:" + Thread.CurrentThread.ManagedThreadId + "\r");                stream.Disconnect();            }        }    }}
客户端的功能是不断的发出获得新id的请求,并打印新id,在客户端可以配置服务端的服务器IP。
如下代码:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace IDClient{    class Program    {        private const string PIPE_NAME = "testNetworkPipe";        static void Main(string[] args)        {            Console.WriteLine("请输入任何字符回车开始执行程序..");            Console.Read();            do            {                //内网服务器ip,必须是局域网                string serverName = "127.0.0.1";                //声明NamedPipeClientStream实例                using (var clientStream = new System.IO.Pipes.NamedPipeClientStream(serverName, PIPE_NAME))                {                    //连接服务器                    clientStream.Connect(1000);                    //设置为消息读取模式                    clientStream.ReadMode = System.IO.Pipes.PipeTransmissionMode.Message;                    do                    {                        byte[] bytes = new byte[4];                        clientStream.Read(bytes, 0, 4);                        int val = BitConverter.ToInt32(bytes, 0);                        Console.Write("NewID == " + val + "\r");                    } while (!clientStream.IsMessageComplete);                }                Thread.Sleep(1);            } while (true);        }    }}
在sql server中就使用了命名管道在局域网内挂进程通讯。
在声明NamedPipeServerStream实例是可以指定其实例个数,如果实例数超过这个数,就会抛出“所有管道范例都在使用中”的IO异常。
本例不可以在实际项目中使用。

程序源码下载

原创粉丝点击