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