命名管道的C#實現


1.    命名管道簡介

"命名管道"或"命名管線"(Named Pipes)是一種簡單的進程間通信(I P C)機制,Microsoft Windows NT,Windows 2000,Windows 95以及Windows 98均提供了對它的支持(但不包括Windows CE).命名管道可在同一台計算機的不同進程之間,或在跨越一個網絡的不同計算機的不同進程之間,支持可靠的,單向或雙向的數據通信.用命名管道來設計應用程序實際非常簡單,並不需要事先深入掌握基層網絡傳送協議(如T C P / I P或I P X)的知識.這是由於命名管道利用了微軟網絡提供者(M S N P)重定向器,通過一個網絡,在各進程間建立通信.這樣一來,應用程序便不必關心網絡協議的細節.之所以要用命名管道作為自己的網絡通信方案,一項重要的原因是它們充分利用了Windows NT及Windows 2000內建的安全特性.

2.命名管道作用

這里有一個可采納命令管道的例子.假定我們要開發一個數據管理系統,只允許一個指定的用戶組進行操作.想像在自己的辦公室中,有一部計算機,其中保存着公司的秘密.我們要求只有公司的管理人員,才能訪問及處理這些秘密.假定在自己的工作站機器上,公司內的每名員工都可看到網絡上的這台計算機.然而,我們並不希望普通員工取得對機密材料的訪問權.在這種情況下,命名管道可發揮出很好的作用,因為我們可開發一個服務器應用程序,令其以來自客戶機的請求為准,對公司的秘密進行安全操作.服務器可將客戶訪問限制在管理人員身上,用Windows NT或新版Windows 2000自帶的安全機制,便可非常輕松地做到這一點.在此要記住的一個重點是,將命名管道作為一種網絡編程方案使用時,它實際上建立一個簡單的客戶機/服務器數據通信體系,可在其中可靠地傳輸數據.

3. 命名管道優點

使用比較方便,並且不需要聲明端口號之類的,在程序中不需要關心權限之類的。

4. 命名管道限制(我個人認為)

管道只能一對一鏈接通信。

5. 命名管道實現

  5.1 命名管道通訊輔助類

    /// <summary>

    /// pipe命名管道通訊輔助類

    /// </summary>

    public class StreamString

    {

        private Stream ioStream;

        private UnicodeEncoding streamEncoding;

 

        public StreamString(Stream ioStream)

        {

            this.ioStream = ioStream;

            streamEncoding = new UnicodeEncoding();

        }

 

        public string ReadString()

        {

            try

            {

                int len;

                len = ioStream.ReadByte() * 256;

                len += ioStream.ReadByte();

                byte[] inBuffer = new byte[len];

                ioStream.Read(inBuffer, 0, len);

 

                return streamEncoding.GetString(inBuffer);

            }

            catch (Exception)

            {

                return null;

            }

        }

 

        public int WriteString(string outString)

        {

            byte[] outBuffer = streamEncoding.GetBytes(outString);

            int len = outBuffer.Length;

            if (len > UInt16.MaxValue)

            {

                len = (int)UInt16.MaxValue;

            }

            ioStream.WriteByte((byte)(len / 256));

            ioStream.WriteByte((byte)(len & 255));

            ioStream.Write(outBuffer, 0, len);

            ioStream.Flush();

 

            return outBuffer.Length + 2;

        }

    }

 

    /// <summary>

    /// 自定義包裝類

    /// </summary>

    public class StringToStream

    {

        private string Contents;

        private StreamString streamString;

 

        public StringToStream(StreamString ss, string contents)

        {

            Contents = contents;

            streamString = ss;

        }

 

        public void Start()

        {

            //string contents = File.ReadAllText(fn);

            streamString.WriteString(Contents);

        }

}

 

 5.2 命名管道服務器端幫助類

public class PipeHelp

    { 

        private static int numThreads = 1;

        /// <summary>

        /// 啟動管道服通訊務器

        /// </summary>

        public static void PipeSeverSart()

        {

            try

            {

                int i;

                Thread[] servers = new Thread[numThreads];

                Console.WriteLine("Waiting for client connect...\n");

                for (i = 0; i < numThreads; i++)

                {

                    servers[i] = new Thread(ServerThread);

                    servers[i].Start();

                }

            }

            catch (Exception)

            {

                throw new Exception("管道服務啟動失敗.");

                //PipeSeverSart();

            }

        }

 

        /// <summary>

        /// 退出管道。(程序退出時別忘了調用)

        /// </summary>

        public static void PipeSeverClose()

        {

            if (pipeServer != null)

            {

                try

                {

                    pipeServer.Disconnect();

                    pipeServer.Close();

                }

                catch (Exception exception)

                {

                    Console.WriteLine(exception.Message);

                }              

            } 

        }
 

        private static NamedPipeServerStream pipeServer;

 

        /// <summary>

        /// 處理函數

        /// </summary>

        /// <param name="data"></param>

        private static void ServerThread(object data)

        {

            try

            {

                Random reRandom = new Random();

                pipeServer =

                   new NamedPipeServerStream("VisualPlatformPipe", PipeDirection.InOut, numThreads);

                //int threadId = Thread.CurrentThread.ManagedThreadId;

                // Wait for a client to connect

                pipeServer.WaitForConnection();

                StreamString ss = new StreamString(pipeServer);

                //Console.WriteLine("Client connected on thread[{0}].", threadId);

                while (true)

                {

                    try

                    {

                        // Read the request from the client. Once the client has

                        // written to the pipe its security token will be available.

                        //ss.WriteString("I am the one true server!");

 

                        string temp = ss.ReadString();

                        if (temp != null)

                        {

                            if (temp.ToLower() == "close")//客戶端通知服務器客戶端退出

                            {

                                //為了客戶端退出之后,可以再次連接到服務器端,重新設置一下服務i其管道

                                Close();

                                pipeServer = new NamedPipeServerStream("VisualPlatformPipe", PipeDirection.InOut, numThreads);

                                pipeServer.WaitForConnection();

                                ss = new StreamString(pipeServer);

                            }

                            else

                            {

                                StringToStream fileReader = new StringToStream(ss, SystemHelp.BusinessSystemID);

                                pipeServer.RunAsClient(fileReader.Start);

                            }

                        }

                        else////客戶端未通知服務器客戶端退出,客戶端直接異常退出

                        {

                            Close();

                            pipeServer = new NamedPipeServerStream("VisualPlatformPipe", PipeDirection.InOut, numThreads);

                            pipeServer.WaitForConnection();

                            ss = new StreamString(pipeServer);

                        }

 

                    }

                    // Catch the IOException that is raised if the pipe is broken

                    // or disconnected.

                    catch (IOException e)

                    {

                        Console.WriteLine("ERROR: {0}", e.Message);

                    }

                }

            }

            catch (Exception)

            {

                 throw new Exception("管道服務啟動失敗.");

            }

        }

 

        /// <summary>

        /// 退出管道

        /// </summary>

        public static void Close()

        {

            if (pipeServer != null)

            {

                pipeServer.Disconnect();

                pipeServer.Close();

            }

        } 

    }

 

5.3客戶端幫助類

   public class PipeClientHelp

    {

        private static StreamString m_StreamString = null;

        private static NamedPipeClientStream pipeClient = null;

        /// <summary>

        /// 啟動客戶端,連接服務器,只允許連接一次

        /// </summary>

        /// <returns></returns>

        public static bool StartConnection()

        {

            try

            {

                if (pipeClient == null)

                {

                    pipeClient =

                                    new NamedPipeClientStream(".", "VisualPlatformPipe",

                                        PipeDirection.InOut, PipeOptions.None,

                                        TokenImpersonationLevel.Impersonation);

 

                    pipeClient.Connect(100);

                    m_StreamString = new StreamString(pipeClient);

                }

            }

            catch (Exception exception)

            {

                pipeClient = null;

                throw new Exception("未啟動服務器端" + exception.Message);

            }

            return true;

        }

 

        /// <summary>

        /// 通知服務器客戶端即將退出

        /// </summary>

        public static void ClosePipe()

        {

            if (pipeClient != null)

            {

                m_StreamString.WriteString("close");

                m_StreamString = null;

                pipeClient.Close();

                pipeClient = null;

            }

        }

        /// <summary>

        /// 從服務器獲取數據

        /// </summary>

        /// <returns></returns>

        public static string GetSystemID()

        {

            if (m_StreamString != null)

            {

                m_StreamString.WriteString("GetBusinessSystemId");

                return m_StreamString.ReadString();

            }

            return null;

        } 

    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM