反正做了一些複雜的事情不討論,其中比較重要的是程式(client)和主要程式之間的溝通。以前C++時代是用message送COPYDATA方式進行,讓兩個程序之間可以互相通訊。
算是很便利,可以自定義結構傳送。而在C#裡頭,有一個更簡單的方法,叫做Pipe。他也是一種主從架構,和Socket類似,只是設定設更簡單。
在微軟的說明網站上,Pipe可分成匿名(Anonymous)和具名(Named)兩種,顧名思義,匿名就是不用給名稱,直接就可以連線,好處是快速,負荷低,更容易在程序間通訊,不過不能使用於網路間。另外一個具名方式可以一對多,支援在網路及多個伺服器執行巴拉巴拉等等。反正,我是用具名方式說明。
微軟的範例說明當中,利用一個StreamString類別當作中介,把I/O簡化成字串,透過Read/Write方式讀取Client/Server間的訊息,透過這個Class會非常好處理字串訊息。
範例網站在此
上面的網站內容基本上已經完全就可以用了,我只是把他改成視窗,用迴圈做個架構,跟現行公司產品類似,Client端一個命令,Server接收到之後回應Ack的方式。
- 首先Server端部份,需要建立一個具名通道,然後等待Client連線。在我範例,是寫在Button按下之後的動作。
NamedPipeServerStream pipeServer = new NamedPipeServerStream("namepipe", PipeDirection.InOut, 1); // Wait for a client to connect pipeServer.WaitForConnection();
- 然後利用微軟範例裡頭的StreamString類別,對Client送出字串,用意讓Client端知道連線成功。因為Client連線之後,就會從上面的WaitForConnection()之後繼續進行。
StreamString ss = new StreamString(pipeServer); ss.WriteString("Connected!");
- 接著我用迴圈,持續去判斷收到來自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); } }
- 再來是Client部份,一樣最先先建立一個具名(名稱和Server一樣)通道,就可以連線了。
NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", "namepipe", PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.Impersonation); pipeClient.Connect();
- 然後對Server送出字串,理論上應該可以收到來自Server的回應,把這些訊息都顯示在一個TextBox上面。簡單方式如下,我程式只是加上時間顯示。
ss.WriteString(textBoxToServer.Text);//client端也有StreamString class textBoxMsg.Text = ss.ReadString();
source code(Visual Studio 2013)
1 意見:
請問一下,如果我是SYSTEM的APP和Admin的APP,可以彼此用NAMED PIPE嗎?
謝謝!
張貼留言