[C#]兩個程式之間的溝通-使用Pipe方式

又是一個客戶的需求,客戶需要我們程式呼叫第三方軟體,還要這個第三方軟體的數據即時呈現在我們程式畫圖。但這個第三方程式只能輸出log file,只好不斷偵測程式創造這個log file之後,丟個訊息讓主程式知道,然後用唯獨方式去parser這個檔案內的資料。

反正做了一些複雜的事情不討論,其中比較重要的是程式(client)和主要程式之間的溝通。以前C++時代是用message送COPYDATA方式進行,讓兩個程序之間可以互相通訊。
算是很便利,可以自定義結構傳送。而在C#裡頭,有一個更簡單的方法,叫做Pipe。他也是一種主從架構,和Socket類似,只是設定設更簡單。

在微軟的說明網站上,Pipe可分成匿名(Anonymous)和具名(Named)兩種,顧名思義,匿名就是不用給名稱,直接就可以連線,好處是快速,負荷低,更容易在程序間通訊,不過不能使用於網路間。另外一個具名方式可以一對多,支援在網路及多個伺服器執行巴拉巴拉等等。反正,我是用具名方式說明。

微軟的範例說明當中,利用一個StreamString類別當作中介,把I/O簡化成字串,透過Read/Write方式讀取Client/Server間的訊息,透過這個Class會非常好處理字串訊息。

範例網站在此

上面的網站內容基本上已經完全就可以用了,我只是把他改成視窗,用迴圈做個架構,跟現行公司產品類似,Client端一個命令,Server接收到之後回應Ack的方式。

  1. 首先Server端部份,需要建立一個具名通道,然後等待Client連線。在我範例,是寫在Button按下之後的動作。
        NamedPipeServerStream pipeServer =
        new NamedPipeServerStream("namepipe", PipeDirection.InOut, 1);
        // Wait for a client to connect
        pipeServer.WaitForConnection();
    
  2. 然後利用微軟範例裡頭的StreamString類別,對Client送出字串,用意讓Client端知道連線成功。因為Client連線之後,就會從上面的WaitForConnection()之後繼續進行。
        StreamString ss = new StreamString(pipeServer);
        ss.WriteString("Connected!");
    
  3. 接著我用迴圈,持續去判斷收到來自Client的訊息,如果是斷線訊息,就跳出。否則就給回應。
        while(true)
        {
            string cmdstr = ss.ReadString();//from client write
            if (cmdstr == "Disconnect")
            {
                ss.WriteString("Disconnect!");
                System.Threading.Thread.Sleep(100);
                break;
            }
            else
            {
                cmdstr = "(Ack)" + cmdstr;
                ss.WriteString(cmdstr);
            }
        }
    
  4. 再來是Client部份,一樣最先先建立一個具名(名稱和Server一樣)通道,就可以連線了。
        NamedPipeClientStream pipeClient =
        new NamedPipeClientStream(".", "namepipe",
          PipeDirection.InOut, PipeOptions.None,
          TokenImpersonationLevel.Impersonation);
        pipeClient.Connect();
    
  5. 然後對Server送出字串,理論上應該可以收到來自Server的回應,把這些訊息都顯示在一個TextBox上面。簡單方式如下,我程式只是加上時間顯示。
        ss.WriteString(textBoxToServer.Text);//client端也有StreamString class
        textBoxMsg.Text = ss.ReadString();
    
程式執行起來畫面如下,左邊是Server,右邊是Client。Pipe非常簡單使用,時間差看起來也在毫秒等級。如果Server放在遠端,猜測應該也是走TCP/IP架構,只是微軟封裝一個易使用的界面。

 source code(Visual Studio 2013)

1 意見:

Vannes Yang 提到...

請問一下,如果我是SYSTEM的APP和Admin的APP,可以彼此用NAMED PIPE嗎?
謝謝!

搜尋此網誌

總網頁瀏覽量

TK呱呱

Made with by TK