blob: c598658b1d710d73499311c7f9dcba90170a1884 [file] [log] [blame] [view]
Abhishek Kumar2f22e842015-02-20 16:39:32 -08001# gRPC C++ Hello World Tutorial
2
3### Install gRPC
Jan Tattermuschf389e522018-06-12 17:26:31 +02004Make sure you have installed gRPC on your system. Follow the
5[BUILDING.md](../../../BUILDING.md) instructions.
Abhishek Kumar2f22e842015-02-20 16:39:32 -08006
7### Get the tutorial source code
8
Stanley Cheung0a268212015-08-27 14:38:38 -07009The example code for this and our other examples lives in the `examples`
10directory. Clone this repository to your local machine by running the
Abhishek Kumar2f22e842015-02-20 16:39:32 -080011following command:
12
13
14```sh
Mehrdad Afshari976eb7c2017-07-10 21:54:56 +000015$ git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc
Abhishek Kumar2f22e842015-02-20 16:39:32 -080016```
17
Stanley Cheung0a268212015-08-27 14:38:38 -070018Change your current directory to examples/cpp/helloworld
Abhishek Kumar2f22e842015-02-20 16:39:32 -080019
20```sh
Stanley Cheung0a268212015-08-27 14:38:38 -070021$ cd examples/cpp/helloworld/
Abhishek Kumar2f22e842015-02-20 16:39:32 -080022```
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
yang-gb00a3f62015-08-28 14:19:37 -070037[helloworld.proto](../../protos/helloworld.proto). The `Greeting`
Abhishek Kumar2f22e842015-02-20 16:39:32 -080038service 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
James Eady2e9ce912015-11-04 14:54:50 -050044```protobuf
Abhishek Kumar2f22e842015-02-20 16:39:32 -080045syntax = "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
Nicolas "Pixel" Nobleb6413de2015-04-10 00:24:09 +020081$ make helloworld.grpc.pb.cc helloworld.pb.cc
Abhishek Kumar2f22e842015-02-20 16:39:32 -080082```
83Which internally invokes the proto-compiler as:
84
85```sh
Nicolas "Pixel" Nobleb6413de2015-04-10 00:24:09 +020086$ protoc -I ../../protos/ --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin ../../protos/helloworld.proto
87$ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto
Abhishek Kumar2f22e842015-02-20 16:39:32 -080088```
89
90### Writing a client
91
yang-g0c633512015-08-26 15:08:43 -070092- 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
James Eady2e9ce912015-11-04 14:54:50 -050096 ```cpp
Julien Boeuf8c48a2a2015-10-17 22:23:02 -070097 auto channel = CreateChannel("localhost:50051", InsecureChannelCredentials());
yang-g0c633512015-08-26 15:08:43 -070098 ```
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
James Eady2e9ce912015-11-04 14:54:50 -0500103 ```cpp
yang-g0c633512015-08-26 15:08:43 -0700104 auto stub = helloworld::Greeter::NewStub(channel);
105 ```
106
107- Make a unary rpc, with `ClientContext` and request/response proto messages.
108
James Eady2e9ce912015-11-04 14:54:50 -0500109 ```cpp
yang-g0c633512015-08-26 15:08:43 -0700110 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
James Eady2e9ce912015-11-04 14:54:50 -0500119 ```cpp
yang-g0c633512015-08-26 15:08:43 -0700120 if (status.ok()) {
121 // check reply.message()
122 } else {
123 // rpc failed.
124 }
125 ```
126
yang-gb00a3f62015-08-28 14:19:37 -0700127For a working example, refer to [greeter_client.cc](greeter_client.cc).
Abhishek Kumar2f22e842015-02-20 16:39:32 -0800128
129### Writing a server
130
yang-g0c633512015-08-26 15:08:43 -0700131- Implement the service interface
132
James Eady2e9ce912015-11-04 14:54:50 -0500133 ```cpp
yang-g0c633512015-08-26 15:08:43 -0700134 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
James Eady2e9ce912015-11-04 14:54:50 -0500147 ```cpp
yang-g0c633512015-08-26 15:08:43 -0700148 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
yang-gb00a3f62015-08-28 14:19:37 -0700155For a working example, refer to [greeter_server.cc](greeter_server.cc).
yang-g0c633512015-08-26 15:08:43 -0700156
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
yang-g2add9802015-08-27 13:03:49 -0700163- call `CompletionQueue::Next` to wait for operations to complete. If a tag
164 appears, it indicates that the corresponding operation is complete.
yang-g0c633512015-08-26 15:08:43 -0700165
166#### Async client
167
168The channel and stub creation code is the same as the sync client.
169
yang-g2add9802015-08-27 13:03:49 -0700170- Initiate the rpc and create a handle for the rpc. Bind the rpc to a
171 `CompletionQueue`.
yang-g0c633512015-08-26 15:08:43 -0700172
James Eady2e9ce912015-11-04 14:54:50 -0500173 ```cpp
yang-g0c633512015-08-26 15:08:43 -0700174 CompletionQueue cq;
175 auto rpc = stub->AsyncSayHello(&context, request, &cq);
176 ```
177
178- Ask for reply and final status, with a unique tag
179
James Eady2e9ce912015-11-04 14:54:50 -0500180 ```cpp
yang-g0c633512015-08-26 15:08:43 -0700181 Status status;
182 rpc->Finish(&reply, &status, (void*)1);
183 ```
184
yang-g2add9802015-08-27 13:03:49 -0700185- 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.
yang-g0c633512015-08-26 15:08:43 -0700187
James Eady2e9ce912015-11-04 14:54:50 -0500188 ```cpp
yang-g0c633512015-08-26 15:08:43 -0700189 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
yang-gb00a3f62015-08-28 14:19:37 -0700197For a working example, refer to [greeter_async_client.cc](greeter_async_client.cc).
yang-g0c633512015-08-26 15:08:43 -0700198
199#### Async server
200
yang-g2add9802015-08-27 13:03:49 -0700201The server implementation requests a rpc call with a tag and then wait for the
202completion queue to return the tag. The basic flow is
yang-g0c633512015-08-26 15:08:43 -0700203
204- Build a server exporting the async service
205
James Eady2e9ce912015-11-04 14:54:50 -0500206 ```cpp
yang-g0c633512015-08-26 15:08:43 -0700207 helloworld::Greeter::AsyncService service;
208 ServerBuilder builder;
209 builder.AddListeningPort("0.0.0.0:50051", InsecureServerCredentials());
Yuchen Zengc67a8ec2016-03-17 11:36:59 -0700210 builder.RegisterService(&service);
yang-g0c633512015-08-26 15:08:43 -0700211 auto cq = builder.AddCompletionQueue();
212 auto server = builder.BuildAndStart();
213 ```
214
215- Request one rpc
216
James Eady2e9ce912015-11-04 14:54:50 -0500217 ```cpp
yang-g0c633512015-08-26 15:08:43 -0700218 ServerContext context;
219 HelloRequest request;
220 ServerAsyncResponseWriter<HelloReply> responder;
221 service.RequestSayHello(&context, &request, &responder, &cq, &cq, (void*)1);
222 ```
223
yang-g2add9802015-08-27 13:03:49 -0700224- Wait for the completion queue to return the tag. The context, request and
225 responder are ready once the tag is retrieved.
yang-g0c633512015-08-26 15:08:43 -0700226
James Eady2e9ce912015-11-04 14:54:50 -0500227 ```cpp
yang-g0c633512015-08-26 15:08:43 -0700228 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
yang-g2add9802015-08-27 13:03:49 -0700239- Wait for the completion queue to return the tag. The rpc is finished when the
240 tag is back.
yang-g0c633512015-08-26 15:08:43 -0700241
James Eady2e9ce912015-11-04 14:54:50 -0500242 ```cpp
yang-g0c633512015-08-26 15:08:43 -0700243 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
yang-gb00a3f62015-08-28 14:19:37 -0700256For a working example, refer to [greeter_async_server.cc](greeter_async_server.cc).
yang-g0c633512015-08-26 15:08:43 -0700257
258
259
260