dot net core 使用 IPC 進程通信
本文告訴大家如何使用dot net core 和其他進程進行通信。
文章目錄
- dot net core 使用 IPC 進程通信
- 原理
- 例子
- 序列化
一般都是使用 WCF 或 remoting 做遠程通信,但是 dot net core 不支持 WCF 所以暫時我就只能使用 管道通信。
原理
管道通信使用的是 Pipe 需要啟動一對服務器和客戶端才可以使用。在 NamedPipeServerStream 啟動之后可以接受其他 NamedPipeClientStream 連接。
因為現在已經使用了 await 了,所以建議全部都可以寫異步,古老的程序員喜歡使用回調,但是現在的程序員還是建議使用 await 比較好,因為比較容易用。
創建的 NamedPipeServerStream 需要告訴管道的命名,和通信方式,通信可以分為單向和雙向,大家使用枚舉去看一下就可以知道。我來創建一個管道名是lindexi
,可以雙向通信的管道。
var pipe = new NamedPipeServerStream("lindexi", PipeDirection.InOut);
上面代碼就創建了一個管道,之后需要等待有連接才可以發送數據。
await pipe.WaitForConnectionAsync();
等待了連接之后,就可以發送數據,發生的數據使用的是字節發送,所以需要轉換編碼。
string str = "發送消息";var spxnfSrxldhhv = Encoding.UTF8.GetBytes(str);pipe.Write(spxnfSrxldhhv, 0, spxnfSrxldhhv.Length);
注意,需要指定發送數據的長度和數據,通過這個方法發送是不建議的。
如果需要使用一個比較高級的方法傳輸,請看文章最后
這時另一個程序就需要下面代碼連接
var pipe = new NamedPipeClientStream(".", "lindexi", PipeDirection.InOut, PipeOptions.None);pipe.Connect()
上面代碼使用的 NamedPipeClientStream 需要指定管道的命名才可以找到。
連接之后可以通過這個方式讀取數據
var spxnfSrxldhhv = new byte[65535];var n = pipe.Read(spxnfSrxldhhv, 0, spxnfSrxldhhv.Length);var str = Encoding.UTF8.GetString(spxnfSrxldhhv, 0, n);
對于讀寫數據很多時候就使用 pipe 的讀寫,寫入字節,讀出字節。
因為一次讀取可能會卡很多時間,所以建議使用異步讀。
如果覺得每次發送都需要轉 byte 然后進行寫,代碼很多,可以使用下面的代碼
var stream = new StreamWriter(pipe);stream.Write("發送消息");stream.Flush();
注意不要使用下面的代碼
using (var stream = new StreamWriter(pipe)){stream.Write("發送消息");}
原因是 using 會關閉 pipe 所以使用之后就不能在寫。
例子
首先創建兩個程序,一個是 WPF 程序 DgvlzKixtdin ,另一個是 dot net core 控制臺 HclkvyDanuiag 。接著需要從 DgvlzKixtdin 發送數據,從 HclkvyDanuiag 接收數據。
在 WPF 程序添加一個 TextBlock 和 Button ,點擊 Button 就發送消息到 dot net core 程序。收到消息就在 TextBlock 顯示。
在 Button 點擊的代碼寫下面代碼
private async void HixKkikjgp_OnClick(object sender, RoutedEventArgs e){var pipe = new NamedPipeServerStream("lindexi", PipeDirection.InOut);await pipe.WaitForConnectionAsync();string str = "發送消息";var spxnfSrxldhhv = Encoding.UTF8.GetBytes(str);pipe.Write(spxnfSrxldhhv, 0, spxnfSrxldhhv.Length);spxnfSrxldhhv = new byte[100];var n = pipe.Read(spxnfSrxldhhv, 0, 100);str = Encoding.UTF8.GetString(spxnfSrxldhhv, 0, n);TjdsguhmKzj.Text = str;}
然后在 dot net core 程序寫下面代碼
static void Main(string[] args){Console.WriteLine("Hello World!");var pipe = new NamedPipeClientStream(".", "lindexi", PipeDirection.InOut, PipeOptions.None);pipe.Connect();var spxnfSrxldhhv = new byte[65535];var n = pipe.Read(spxnfSrxldhhv, 0, spxnfSrxldhhv.Length);var str = Encoding.UTF8.GetString(spxnfSrxldhhv, 0, n);Console.WriteLine(str);str = "收到";spxnfSrxldhhv = Encoding.UTF8.GetBytes(str);pipe.Write(spxnfSrxldhhv, 0, spxnfSrxldhhv.Length);Console.Read();}
先啟動 WPF 程序,然后啟動控制臺
這時點擊按鈕之后就打開控制臺可以看到控制臺可以收到消息
然后 WPF 也收到控制臺發過來的消息
序列化
雖然使用StreamWriter可以減少寫入讀取的代碼,但是實際上這樣只能用來傳字符串,需要把類傳輸還是比較難,所以我找到了 Protobuf ,使用這個庫可以簡單使用。
首先打開 Nuget 安裝 Protobuf 第一個
我這里使用 protobuf-net
然后創建一個類用來傳輸
[ProtoContract]public class TyfxxTlkbjn{public string DczSwdsun { get; set; }}
使用下面代碼可以進行寫入
Serializer.Serialize(pipe, 實例);
所以修改一下上面的按鈕按下
{var pipe = new NamedPipeServerStream("lindexi", PipeDirection.InOut);await pipe.WaitForConnectionAsync();var tyfxxTlkbjn = new TyfxxTlkbjn(){DczSwdsun = "發送消息"};Serializer.Serialize(pipe, tyfxxTlkbjn);pipe.Disconnect();
修改 dot net core的代碼
static void Main(string[] args){var pipe = new NamedPipeClientStream(".", "lindexi", PipeDirection.InOut, PipeOptions.None);pipe.Connect();var tyfxxTlkbjn = Serializer.Deserialize<TyfxxTlkbjn>(pipe);Console.WriteLine(tyfxxTlkbjn.DczSwdsun);Console.Read();}
如果使用 wcf 請看 .NET Core調用WCF的最佳實踐
如果需要使用 grpc 請看.net core grpc 實現通信
我搭建了自己的博客 https://lindexi.gitee.io/ 歡迎大家訪問,里面有很多新的博客。只有在我看到博客寫成熟之后才會放在csdn或博客園,但是一旦發布了就不再更新
如果在博客看到有任何不懂的,歡迎交流,我搭建了 dotnet 職業技術學院 歡迎大家加入
本作品采用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名林德熙(包含鏈接:http://blog.csdn.net/lindexi_gd ),不得用于商業目的,基于本文修改后的作品務必以相同的許可發布。如有任何疑問,請與我聯系。