目的:實現在一台機器上使用gRPC搭建服務器和客戶端環境,並進行一次通信
參考博客:https://www.cnblogs.com/linezero/p/grpc.html
一、新建項目
1、打開VS,新建一個名為gRPCDemo的C#類庫,在類庫項目的properties中選擇目標框架為Net Standard 1.5
2、創建成功后,在解決方案資源管理器中,右鍵“解決方案gRPCDemo”,點擊添加中的新建項目,依此創建兩個控制台程序,分別命名為grpcServer、grpcClient,最終解決方案目錄如下:
二、定義服務
1、創建定義服務的文件.proto
右擊上面創建好黑色的gRPCDemo項目,點擊添加 -> 新建項目 ,在名稱中直接填寫:helloworld.proto
2、打開該創建的文件,定義服務方法,主要定義SayHello rpc 方法。原理如果想看懂建議看開頭推薦的兩篇博文
//定義服務的代碼,放在剛創建的helloworld.proto中
//定義服務的代碼,放在剛創建的helloworld.proto中
syntax = "proto3"; package gRPCDemo; service gRPC { rpc SayHello (HelloRequest) returns (HelloReply) {} } message HelloRequest { string name = 1; } message HelloReply { string message = 1; }
三、使用GRPC.Tools生成代碼
上一步服務定義成功了,我們開始生成客戶端和服務端的代碼。
1、首先在VS中對3個項目添加工具包引用
右鍵點擊“解決方案gRPCDemo”,點擊“管理解決方案的NuGet程序包”,在瀏覽中分別搜索"Grpc"、"Grpc.Tools"、"Google.Protobuf",然后點擊右面項目,全選,再點擊安裝(也可以用視圖 -> 窗口 -> 程序包管理器控制台 中的"Install-Package Grpc"進行這一步,這里不提供這種方法,有興趣自己百度)。
2、拷貝工具包到文件夾中
(1)首先,系統里找到protoc.exe和grpc_csharp_plugin.exe(位置多半會在C:\Users\Administrator\.nuget\packages\grpc.tools\1.17.1\tools\windows_x64 ,如果不在可以用everything搜索前面的工具名)
(2)然后在自己的VS工程文件夾中建立一個新文件夾命名為packages , 並將上面找到的.nuget\packages中的“Google.protobuf”、“grpc”、“grpc.tools”文件夾拷貝到我們工程文件夾下的packages里面。
3、使用工具生成代碼
(1)在系統中運行cmd,運行下圖指令進入到我們的工程文件夾里,也就是packages的上一層
(2)然后編寫以下指令並運行:
這里參數需要詳細說明一下(摘抄自:入門干貨之Grpc的.Net 封裝-MagicOnion),在這里卡了很長時間:
1. -I 指定一個或者多個目錄,用來搜索.proto文件的,如果不指定,那就是當前目錄,因為-I已經指定了。
2、 --csharp_out 用來生成C#代碼,當然了還能cpp_out、java_out、javanano_out、js_out、objc_out、php_out、python_out、ruby_out 這時候你就應該知道,這玩意就是支持多語言的,才用的,生成一些文件,然后給各個語言平台調用。參數1是輸出路徑,參數2是proto的文件名或者路徑。
3、--grpc_out 到這里可能有人會懵逼,咋回事?C#不是有一個自己的輸出目錄么?怎么又一個輸出?
csharp_out是輸出類似於咱們平時寫的實體類,接口,定義之類的。生成的文件叫,額,就叫xxx.cs吧.
grpc_out是跟服務相關,創建,調用,綁定,實現相關。生成的玩意叫xxxGrpc.cs。 對比上個選項生成的文件名,大概能了解個十之八九吧。
4、--plugin=protoc-gen-grpc=grpc_csharp_plugin.exe 這個就是c#的插件,python有python的,java有java的。必須要指定它。
以上指令回車運行即可,這里需要說明具體的文件夾路徑還是要改一下,因為每個人文件所在目錄是不同的,這里要注意,否則cmd會告訴你找不到指定路徑
packages\grpc.tools\1.17.1\tools\windows_x86\protoc.exe -IgRPCDemo --csharp_out GRPCDemo gRPCDemo\helloworld.proto --grpc_out gRPCDemo --plugin=protoc-gen-grpc=packages\grpc.tools\1.17.1\tools\windows_x86\grpc_csharp_plugin.exe
執行完之后,就可以看到目錄下多了很多生成的文件
(3)添加工程,在VS里項目右鍵-> 添加 -> 現有項目 ,然后選擇剛生成的文件進去就可以了;
(4)引用項目:在gRPCSever和gRPCClient項目中分別引用gRPCDemo,操作是右擊項目的依賴項->添加引用 -> 解決方案 -> 點擊gRPCDemo ,確定即可。
四、創建客戶端和服務端
1、創建服務端:
在gRPCSever項目里打開program.cs,復制進去一下代碼:
//服務端代碼 using Grpc.Core; using GRPCDemo; using System; using System.Threading.Tasks; namespace gRPCServer { class severProgram { const int Port = 9007; public static void Main(string[] args) { Server server = new Server { Services = { gRPC.BindService(new gRPCImpl()) }, Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) } }; server.Start(); Console.WriteLine("gRPC server listening on port " + Port); Console.WriteLine("任意鍵退出..."); Console.ReadKey(); server.ShutdownAsync().Wait(); } } class gRPCImpl : gRPC.gRPCBase { // 實現SayHello方法 public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context) { return Task.FromResult(new HelloReply { Message = "Hello " + request.Name }); } } }
2、創建客戶端:
在gRPCClient項目里打開program.cs,復制進去一下代碼:
//客戶端代碼 using Grpc.Core; using GRPCDemo; using System; namespace gRPCClient { class Program { static void Main(string[] args) { Channel channel = new Channel("127.0.0.1:9007", ChannelCredentials.Insecure); var client = new gRPC.gRPCClient(channel); var reply = client.SayHello(new HelloRequest { Name = "Zhang San" }); Console.WriteLine("來自" + reply.Message); channel.ShutdownAsync().Wait(); Console.WriteLine("任意鍵退出..."); Console.ReadKey(); } } }
3、生成項目文件:右擊gRPCClient和gRPCSever分別生成
4、用vs打開項目,如下圖配置,運行
結果是這樣的服務(運行完別關閉窗口,服務需要一直運行):
5、再用vs第二次打開該項目,如下圖配置,運行
結果就再服務端調用了信息並返回到客戶端,結果如下:
截止到現在,成功實現利用gRPC進行通信。
代碼生成工具:https://files.cnblogs.com/files/blogs/667310/ProtoEditer.rar