Index: third_party/grpc/examples/cpp/helloworld/README.md |
diff --git a/third_party/grpc/examples/cpp/helloworld/README.md b/third_party/grpc/examples/cpp/helloworld/README.md |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8e11f7cdf3ee893858d261c75c4586aa13b16b1c |
--- /dev/null |
+++ b/third_party/grpc/examples/cpp/helloworld/README.md |
@@ -0,0 +1,260 @@ |
+# gRPC C++ Hello World Tutorial |
+ |
+### Install gRPC |
+Make sure you have installed gRPC on your system. Follow the instructions here: |
+[https://github.com/grpc/grpc/blob/master/INSTALL](../../../INSTALL.md). |
+ |
+### Get the tutorial source code |
+ |
+The example code for this and our other examples lives in the `examples` |
+directory. Clone this repository to your local machine by running the |
+following command: |
+ |
+ |
+```sh |
+$ git clone https://github.com/grpc/grpc.git |
+``` |
+ |
+Change your current directory to examples/cpp/helloworld |
+ |
+```sh |
+$ cd examples/cpp/helloworld/ |
+``` |
+ |
+### Defining a service |
+ |
+The first step in creating our example is to define a *service*: an RPC |
+service specifies the methods that can be called remotely with their parameters |
+and return types. As you saw in the |
+[overview](#protocolbuffers) above, gRPC does this using [protocol |
+buffers](https://developers.google.com/protocol-buffers/docs/overview). We |
+use the protocol buffers interface definition language (IDL) to define our |
+service methods, and define the parameters and return |
+types as protocol buffer message types. Both the client and the |
+server use interface code generated from the service definition. |
+ |
+Here's our example service definition, defined using protocol buffers IDL in |
+[helloworld.proto](../../protos/helloworld.proto). The `Greeting` |
+service has one method, `hello`, that lets the server receive a single |
+`HelloRequest` |
+message from the remote client containing the user's name, then send back |
+a greeting in a single `HelloReply`. This is the simplest type of RPC you |
+can specify in gRPC - we'll look at some other types later in this document. |
+ |
+```protobuf |
+syntax = "proto3"; |
+ |
+option java_package = "ex.grpc"; |
+ |
+package helloworld; |
+ |
+// The greeting service definition. |
+service Greeter { |
+ // Sends a greeting |
+ rpc SayHello (HelloRequest) returns (HelloReply) {} |
+} |
+ |
+// The request message containing the user's name. |
+message HelloRequest { |
+ string name = 1; |
+} |
+ |
+// The response message containing the greetings |
+message HelloReply { |
+ string message = 1; |
+} |
+ |
+``` |
+ |
+<a name="generating"></a> |
+### Generating gRPC code |
+ |
+Once we've defined our service, we use the protocol buffer compiler |
+`protoc` to generate the special client and server code we need to create |
+our application. The generated code contains both stub code for clients to |
+use and an abstract interface for servers to implement, both with the method |
+defined in our `Greeting` service. |
+ |
+To generate the client and server side interfaces: |
+ |
+```sh |
+$ make helloworld.grpc.pb.cc helloworld.pb.cc |
+``` |
+Which internally invokes the proto-compiler as: |
+ |
+```sh |
+$ protoc -I ../../protos/ --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin ../../protos/helloworld.proto |
+$ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto |
+``` |
+ |
+### Writing a client |
+ |
+- Create a channel. A channel is a logical connection to an endpoint. A gRPC |
+ channel can be created with the target address, credentials to use and |
+ arguments as follows |
+ |
+ ```cpp |
+ auto channel = CreateChannel("localhost:50051", InsecureChannelCredentials()); |
+ ``` |
+ |
+- Create a stub. A stub implements the rpc methods of a service and in the |
+ generated code, a method is provided to created a stub with a channel: |
+ |
+ ```cpp |
+ auto stub = helloworld::Greeter::NewStub(channel); |
+ ``` |
+ |
+- Make a unary rpc, with `ClientContext` and request/response proto messages. |
+ |
+ ```cpp |
+ ClientContext context; |
+ HelloRequest request; |
+ request.set_name("hello"); |
+ HelloReply reply; |
+ Status status = stub->SayHello(&context, request, &reply); |
+ ``` |
+ |
+- Check returned status and response. |
+ |
+ ```cpp |
+ if (status.ok()) { |
+ // check reply.message() |
+ } else { |
+ // rpc failed. |
+ } |
+ ``` |
+ |
+For a working example, refer to [greeter_client.cc](greeter_client.cc). |
+ |
+### Writing a server |
+ |
+- Implement the service interface |
+ |
+ ```cpp |
+ class GreeterServiceImpl final : public Greeter::Service { |
+ Status SayHello(ServerContext* context, const HelloRequest* request, |
+ HelloReply* reply) override { |
+ std::string prefix("Hello "); |
+ reply->set_message(prefix + request->name()); |
+ return Status::OK; |
+ } |
+ }; |
+ |
+ ``` |
+ |
+- Build a server exporting the service |
+ |
+ ```cpp |
+ GreeterServiceImpl service; |
+ ServerBuilder builder; |
+ builder.AddListeningPort("0.0.0.0:50051", grpc::InsecureServerCredentials()); |
+ builder.RegisterService(&service); |
+ std::unique_ptr<Server> server(builder.BuildAndStart()); |
+ ``` |
+ |
+For a working example, refer to [greeter_server.cc](greeter_server.cc). |
+ |
+### Writing asynchronous client and server |
+ |
+gRPC uses `CompletionQueue` API for asynchronous operations. The basic work flow |
+is |
+- bind a `CompletionQueue` to a rpc call |
+- do something like a read or write, present with a unique `void*` tag |
+- call `CompletionQueue::Next` to wait for operations to complete. If a tag |
+ appears, it indicates that the corresponding operation is complete. |
+ |
+#### Async client |
+ |
+The channel and stub creation code is the same as the sync client. |
+ |
+- Initiate the rpc and create a handle for the rpc. Bind the rpc to a |
+ `CompletionQueue`. |
+ |
+ ```cpp |
+ CompletionQueue cq; |
+ auto rpc = stub->AsyncSayHello(&context, request, &cq); |
+ ``` |
+ |
+- Ask for reply and final status, with a unique tag |
+ |
+ ```cpp |
+ Status status; |
+ rpc->Finish(&reply, &status, (void*)1); |
+ ``` |
+ |
+- Wait for the completion queue to return the next tag. The reply and status are |
+ ready once the tag passed into the corresponding `Finish()` call is returned. |
+ |
+ ```cpp |
+ void* got_tag; |
+ bool ok = false; |
+ cq.Next(&got_tag, &ok); |
+ if (ok && got_tag == (void*)1) { |
+ // check reply and status |
+ } |
+ ``` |
+ |
+For a working example, refer to [greeter_async_client.cc](greeter_async_client.cc). |
+ |
+#### Async server |
+ |
+The server implementation requests a rpc call with a tag and then wait for the |
+completion queue to return the tag. The basic flow is |
+ |
+- Build a server exporting the async service |
+ |
+ ```cpp |
+ helloworld::Greeter::AsyncService service; |
+ ServerBuilder builder; |
+ builder.AddListeningPort("0.0.0.0:50051", InsecureServerCredentials()); |
+ builder.RegisterAsyncService(&service); |
+ auto cq = builder.AddCompletionQueue(); |
+ auto server = builder.BuildAndStart(); |
+ ``` |
+ |
+- Request one rpc |
+ |
+ ```cpp |
+ ServerContext context; |
+ HelloRequest request; |
+ ServerAsyncResponseWriter<HelloReply> responder; |
+ service.RequestSayHello(&context, &request, &responder, &cq, &cq, (void*)1); |
+ ``` |
+ |
+- Wait for the completion queue to return the tag. The context, request and |
+ responder are ready once the tag is retrieved. |
+ |
+ ```cpp |
+ HelloReply reply; |
+ Status status; |
+ void* got_tag; |
+ bool ok = false; |
+ cq.Next(&got_tag, &ok); |
+ if (ok && got_tag == (void*)1) { |
+ // set reply and status |
+ responder.Finish(reply, status, (void*)2); |
+ } |
+ ``` |
+ |
+- Wait for the completion queue to return the tag. The rpc is finished when the |
+ tag is back. |
+ |
+ ```cpp |
+ void* got_tag; |
+ bool ok = false; |
+ cq.Next(&got_tag, &ok); |
+ if (ok && got_tag == (void*)2) { |
+ // clean up |
+ } |
+ ``` |
+ |
+To handle multiple rpcs, the async server creates an object `CallData` to |
+maintain the state of each rpc and use the address of it as the unique tag. For |
+simplicity the server only uses one completion queue for all events, and runs a |
+main loop in `HandleRpcs` to query the queue. |
+ |
+For a working example, refer to [greeter_async_server.cc](greeter_async_server.cc). |
+ |
+ |
+ |
+ |