README.md
1# gRPC C++ Hello World Tutorial
2
3### Install gRPC
4Make sure you have installed gRPC on your system. Follow the
5[BUILDING.md](../../../BUILDING.md) instructions.
6
7### Get the tutorial source code
8
9The example code for this and our other examples lives in the `examples`
10directory. Clone this repository to your local machine by running the
11following command:
12
13
14```sh
15$ git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc
16```
17
18Change your current directory to examples/cpp/helloworld
19
20```sh
21$ cd examples/cpp/helloworld/
22```
23
24### Defining a service
25
26The first step in creating our example is to define a *service*: an RPC
27service specifies the methods that can be called remotely with their parameters
28and return types. As you saw in the
29[overview](#protocolbuffers) above, gRPC does this using [protocol
30buffers](https://developers.google.com/protocol-buffers/docs/overview). We
31use the protocol buffers interface definition language (IDL) to define our
32service methods, and define the parameters and return
33types as protocol buffer message types. Both the client and the
34server use interface code generated from the service definition.
35
36Here's our example service definition, defined using protocol buffers IDL in
37[helloworld.proto](../../protos/helloworld.proto). The `Greeting`
38service has one method, `hello`, that lets the server receive a single
39`HelloRequest`
40message from the remote client containing the user's name, then send back
41a greeting in a single `HelloReply`. This is the simplest type of RPC you
42can specify in gRPC - we'll look at some other types later in this document.
43
44```protobuf
45syntax = "proto3";
46
47option java_package = "ex.grpc";
48
49package helloworld;
50
51// The greeting service definition.
52service Greeter {
53 // Sends a greeting
54 rpc SayHello (HelloRequest) returns (HelloReply) {}
55}
56
57// The request message containing the user's name.
58message HelloRequest {
59 string name = 1;
60}
61
62// The response message containing the greetings
63message HelloReply {
64 string message = 1;
65}
66
67```
68
69<a name="generating"></a>
70### Generating gRPC code
71
72Once we've defined our service, we use the protocol buffer compiler
73`protoc` to generate the special client and server code we need to create
74our application. The generated code contains both stub code for clients to
75use and an abstract interface for servers to implement, both with the method
76defined in our `Greeting` service.
77
78To generate the client and server side interfaces:
79
80```sh
81$ make helloworld.grpc.pb.cc helloworld.pb.cc
82```
83Which internally invokes the proto-compiler as:
84
85```sh
86$ protoc -I ../../protos/ --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin ../../protos/helloworld.proto
87$ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto
88```
89
90### Writing a client
91
92- Create a channel. A channel is a logical connection to an endpoint. A gRPC
93 channel can be created with the target address, credentials to use and
94 arguments as follows
95
96 ```cpp
97 auto channel = CreateChannel("localhost:50051", InsecureChannelCredentials());
98 ```
99
100- Create a stub. A stub implements the rpc methods of a service and in the
101 generated code, a method is provided to created a stub with a channel:
102
103 ```cpp
104 auto stub = helloworld::Greeter::NewStub(channel);
105 ```
106
107- Make a unary rpc, with `ClientContext` and request/response proto messages.
108
109 ```cpp
110 ClientContext context;
111 HelloRequest request;
112 request.set_name("hello");
113 HelloReply reply;
114 Status status = stub->SayHello(&context, request, &reply);
115 ```
116
117- Check returned status and response.
118
119 ```cpp
120 if (status.ok()) {
121 // check reply.message()
122 } else {
123 // rpc failed.
124 }
125 ```
126
127For a working example, refer to [greeter_client.cc](greeter_client.cc).
128
129### Writing a server
130
131- Implement the service interface
132
133 ```cpp
134 class GreeterServiceImpl final : public Greeter::Service {
135 Status SayHello(ServerContext* context, const HelloRequest* request,
136 HelloReply* reply) override {
137 std::string prefix("Hello ");
138 reply->set_message(prefix + request->name());
139 return Status::OK;
140 }
141 };
142
143 ```
144
145- Build a server exporting the service
146
147 ```cpp
148 GreeterServiceImpl service;
149 ServerBuilder builder;
150 builder.AddListeningPort("0.0.0.0:50051", grpc::InsecureServerCredentials());
151 builder.RegisterService(&service);
152 std::unique_ptr<Server> server(builder.BuildAndStart());
153 ```
154
155For a working example, refer to [greeter_server.cc](greeter_server.cc).
156
157### Writing asynchronous client and server
158
159gRPC uses `CompletionQueue` API for asynchronous operations. The basic work flow
160is
161- bind a `CompletionQueue` to a rpc call
162- do something like a read or write, present with a unique `void*` tag
163- call `CompletionQueue::Next` to wait for operations to complete. If a tag
164 appears, it indicates that the corresponding operation is complete.
165
166#### Async client
167
168The channel and stub creation code is the same as the sync client.
169
170- Initiate the rpc and create a handle for the rpc. Bind the rpc to a
171 `CompletionQueue`.
172
173 ```cpp
174 CompletionQueue cq;
175 auto rpc = stub->AsyncSayHello(&context, request, &cq);
176 ```
177
178- Ask for reply and final status, with a unique tag
179
180 ```cpp
181 Status status;
182 rpc->Finish(&reply, &status, (void*)1);
183 ```
184
185- Wait for the completion queue to return the next tag. The reply and status are
186 ready once the tag passed into the corresponding `Finish()` call is returned.
187
188 ```cpp
189 void* got_tag;
190 bool ok = false;
191 cq.Next(&got_tag, &ok);
192 if (ok && got_tag == (void*)1) {
193 // check reply and status
194 }
195 ```
196
197For a working example, refer to [greeter_async_client.cc](greeter_async_client.cc).
198
199#### Async server
200
201The server implementation requests a rpc call with a tag and then wait for the
202completion queue to return the tag. The basic flow is
203
204- Build a server exporting the async service
205
206 ```cpp
207 helloworld::Greeter::AsyncService service;
208 ServerBuilder builder;
209 builder.AddListeningPort("0.0.0.0:50051", InsecureServerCredentials());
210 builder.RegisterService(&service);
211 auto cq = builder.AddCompletionQueue();
212 auto server = builder.BuildAndStart();
213 ```
214
215- Request one rpc
216
217 ```cpp
218 ServerContext context;
219 HelloRequest request;
220 ServerAsyncResponseWriter<HelloReply> responder;
221 service.RequestSayHello(&context, &request, &responder, &cq, &cq, (void*)1);
222 ```
223
224- Wait for the completion queue to return the tag. The context, request and
225 responder are ready once the tag is retrieved.
226
227 ```cpp
228 HelloReply reply;
229 Status status;
230 void* got_tag;
231 bool ok = false;
232 cq.Next(&got_tag, &ok);
233 if (ok && got_tag == (void*)1) {
234 // set reply and status
235 responder.Finish(reply, status, (void*)2);
236 }
237 ```
238
239- Wait for the completion queue to return the tag. The rpc is finished when the
240 tag is back.
241
242 ```cpp
243 void* got_tag;
244 bool ok = false;
245 cq.Next(&got_tag, &ok);
246 if (ok && got_tag == (void*)2) {
247 // clean up
248 }
249 ```
250
251To handle multiple rpcs, the async server creates an object `CallData` to
252maintain the state of each rpc and use the address of it as the unique tag. For
253simplicity the server only uses one completion queue for all events, and runs a
254main loop in `HandleRpcs` to query the queue.
255
256For a working example, refer to [greeter_async_server.cc](greeter_async_server.cc).
257
258
259
260
261