{"id":6312,"date":"2018-06-23T19:53:18","date_gmt":"2018-06-23T19:53:18","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=6312"},"modified":"2018-06-23T19:55:52","modified_gmt":"2018-06-23T19:55:52","slug":"using-grpc-with-protocol-buffers","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/using-grpc-with-protocol-buffers\/","title":{"rendered":"Using gRPC with Protocol Buffers"},"content":{"rendered":"<p>In the last post, <a href=\"http:\/\/putridparrot.com\/blog\/using-protocol-buffers\/\" rel=\"noopener\" target=\"_blank\">Using Protocol Buffers<\/a>, we looked at creating .proto files and how we generate C# code from them along with how to stream the binary data created by the generated code.<\/p>\n<p>Let&#8217;s now look at how we might like to use Protocol Buffers &#8220;over the wire&#8221;.<\/p>\n<p>Whilst we can write our own sockets code and stream data via this, there&#8217;s a close relationship between gRPC and Protocol Buffers which allows us to generate RPC code using the. proto file.<\/p>\n<p>Let&#8217;s begin by adding a service and a method to the .proto file, so add the following<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\nservice MusicService {\r\n   rpc Query(NotesRequest) returns (NotesResponse) {\r\n   }\r\n}\r\n<\/pre>\n<p><em>In the last post, I mentioned the NoteResponse was designed for use in the remoting code. Here it&#8217;s our return type.<\/em><\/p>\n<p>To generate the gRPC code we need to make some additions to our previously defined Pre-Build event. Before we can do that, we need some more tools installed. So using nuget install the following package, Grpc.Tools, while you&#8217;re at it, if you&#8217;re working with the VS project previously defined, also add the package Grpc.<\/p>\n<p>Now, append the following to the Pre-Build command (formatted to be a little more readable)<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n--grpc_out $(ProjectDir) \r\n--plugin=protoc-gen-grpc=$(SolutionDir)packages\\Grpc.Tools.1.12.0\\tools\\windows_x86\\grpc_csharp_plugin.exe\r\n<\/pre>\n<p>In my case, rebuilding my VS solution will result in a new file <em>MusicGrpc.cs<\/em> which I&#8217;ll need to include in the project.<\/p>\n<p>If you&#8217;ve created a Console application already, this can act as the server, so you&#8217;ll need to create another Console application to be our client. I won&#8217;t go through all the steps for adding the files etc. but let&#8217;s just jump straight into looking at the server code.<\/p>\n<p><strong>The Server<\/strong><\/p>\n<p>Add a new class, mine&#8217;s MusicServer we derive this from the gRPC generated MusicServiceBase, like this<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nusing System.Threading.Tasks;\r\nusing Grpc.Core;\r\nusing PutridParrot.Music;\r\n\r\nnamespace Server\r\n{\r\n    public class MusicServer : MusicService.MusicServiceBase\r\n    {\r\n        public override Task&lt;NotesResponse&gt; Query(\r\n           NotesRequest request, \r\n           ServerCallContext context)\r\n        {\r\n            if (request.Key == Note.C)\r\n            {\r\n                return Task.FromResult(new NotesResponse\r\n                {\r\n                    Name = request.Name,\r\n                    Key = request.Key,\r\n                    Notes =\r\n                    {\r\n                        Note.C, Note.E, Note.G\r\n                    }\r\n                });\r\n            }\r\n            return base.Query(request, context);\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>Obviously the functionality here is rather limited, but you get the idea, the Query method was generated for us by protoc, and we simply supply our implementation.<\/p>\n<p>To run up the server, we change our Main method to look like this<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar server = new Grpc.Core.Server\r\n{\r\n   Services = \r\n   {\r\n      MusicService.BindService(new MusicServer())\r\n   },\r\n   Ports = \r\n   { \r\n      new ServerPort(&quot;127.0.0.1&quot;, \r\n         50051, \r\n         ServerCredentials.Insecure)\r\n   }\r\n};\r\n\r\nserver.Start();\r\n\r\nConsole.ReadKey();\r\nserver.ShutdownAsync().Wait();\r\n<\/pre>\n<p>This is pretty self-explanatory, we supply the Server with the Services and the ports, then start the server.<\/p>\n<p><strong>The Client<\/strong><\/p>\n<p>The client code looks like this<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar channel = new Channel(\r\n   &quot;127.0.0.1:50051&quot;, \r\n   ChannelCredentials.Insecure);\r\n\r\nvar client = new MusicService.MusicServiceClient(channel);\r\n\r\nvar request = new NotesRequest\r\n{\r\n   Key = Note.C,\r\n   Name = &quot;Major&quot;\r\n};\r\n\r\nvar response = client.Query(request);\r\n\r\n\/\/ output the results\r\nforeach (var note in response.Notes)\r\n{\r\n   Console.WriteLine(note);\r\n}\r\n      \r\nchannel.ShutdownAsync().Wait();\r\n<\/pre>\n<p>As you can see, we create a Channel which is the equivalent of a socket connection, passing in the and port information.<\/p>\n<p>Next we create an instance of the MusicServiceClient which was generated by protoc for us. Everything else is as you&#8217;d expect, we create our request object call our rpc method passing in the request and a response object is returned.<\/p>\n<p>Code available here https:\/\/github.com\/putridparrot\/blog-projects\/tree\/master\/ProtocolBuffers\/CSharp<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the last post, Using Protocol Buffers, we looked at creating .proto files and how we generate C# code from them along with how to stream the binary data created by the generated code. Let&#8217;s now look at how we might like to use Protocol Buffers &#8220;over the wire&#8221;. Whilst we can write our own [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[221,220],"tags":[],"class_list":["post-6312","post","type-post","status-publish","format-standard","hentry","category-grpc","category-protocol-buffers"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/6312","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=6312"}],"version-history":[{"count":5,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/6312\/revisions"}],"predecessor-version":[{"id":6322,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/6312\/revisions\/6322"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=6312"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=6312"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=6312"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}