diff options
Diffstat (limited to 'examples/cpp/helloworld')
-rw-r--r-- | examples/cpp/helloworld/Makefile | 119 | ||||
-rw-r--r-- | examples/cpp/helloworld/README.md | 260 | ||||
-rw-r--r-- | examples/cpp/helloworld/greeter_async_client.cc | 98 | ||||
-rw-r--r-- | examples/cpp/helloworld/greeter_async_server.cc | 136 | ||||
-rw-r--r-- | examples/cpp/helloworld/greeter_client.cc | 85 | ||||
-rw-r--r-- | examples/cpp/helloworld/greeter_server.cc | 78 |
6 files changed, 776 insertions, 0 deletions
diff --git a/examples/cpp/helloworld/Makefile b/examples/cpp/helloworld/Makefile new file mode 100644 index 0000000000..f2093afa05 --- /dev/null +++ b/examples/cpp/helloworld/Makefile @@ -0,0 +1,119 @@ +# +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +CXX = g++ +CPPFLAGS += -I/usr/local/include -pthread +CXXFLAGS += -std=c++11 +LDFLAGS += -L/usr/local/lib -lgrpc++_unsecure -lgrpc -lgpr -lprotobuf -lpthread -ldl +PROTOC = protoc +GRPC_CPP_PLUGIN = grpc_cpp_plugin +GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)` + +PROTOS_PATH = ../../protos + +vpath %.proto $(PROTOS_PATH) + +all: system-check greeter_client greeter_server greeter_async_client greeter_async_server + +greeter_client: helloworld.pb.o helloworld.grpc.pb.o greeter_client.o + $(CXX) $^ $(LDFLAGS) -o $@ + +greeter_server: helloworld.pb.o helloworld.grpc.pb.o greeter_server.o + $(CXX) $^ $(LDFLAGS) -o $@ + +greeter_async_client: helloworld.pb.o helloworld.grpc.pb.o greeter_async_client.o + $(CXX) $^ $(LDFLAGS) -o $@ + +greeter_async_server: helloworld.pb.o helloworld.grpc.pb.o greeter_async_server.o + $(CXX) $^ $(LDFLAGS) -o $@ + +%.grpc.pb.cc: %.proto + $(PROTOC) -I $(PROTOS_PATH) --grpc_out=. --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN_PATH) $< + +%.pb.cc: %.proto + $(PROTOC) -I $(PROTOS_PATH) --cpp_out=. $< + +clean: + rm -f *.o *.pb.cc *.pb.h greeter_client greeter_server greeter_async_client greeter_async_server + + +# The following is to test your system and ensure a smoother experience. +# They are by no means necessary to actually compile a grpc-enabled software. + +PROTOC_CMD = which $(PROTOC) +PROTOC_CHECK_CMD = $(PROTOC) --version | grep -q libprotoc.3 +PLUGIN_CHECK_CMD = which $(GRPC_CPP_PLUGIN) +HAS_PROTOC = $(shell $(PROTOC_CMD) > /dev/null && echo true || echo false) +ifeq ($(HAS_PROTOC),true) +HAS_VALID_PROTOC = $(shell $(PROTOC_CHECK_CMD) 2> /dev/null && echo true || echo false) +endif +HAS_PLUGIN = $(shell $(PLUGIN_CHECK_CMD) > /dev/null && echo true || echo false) + +SYSTEM_OK = false +ifeq ($(HAS_VALID_PROTOC),true) +ifeq ($(HAS_PLUGIN),true) +SYSTEM_OK = true +endif +endif + +system-check: +ifneq ($(HAS_VALID_PROTOC),true) + @echo " DEPENDENCY ERROR" + @echo + @echo "You don't have protoc 3.0.0 installed in your path." + @echo "Please install Google protocol buffers 3.0.0 and its compiler." + @echo "You can find it here:" + @echo + @echo " https://github.com/google/protobuf/releases/tag/v3.0.0-alpha-1" + @echo + @echo "Here is what I get when trying to evaluate your version of protoc:" + @echo + -$(PROTOC) --version + @echo + @echo +endif +ifneq ($(HAS_PLUGIN),true) + @echo " DEPENDENCY ERROR" + @echo + @echo "You don't have the grpc c++ protobuf plugin installed in your path." + @echo "Please install grpc. You can find it here:" + @echo + @echo " https://github.com/grpc/grpc" + @echo + @echo "Here is what I get when trying to detect if you have the plugin:" + @echo + -which $(GRPC_CPP_PLUGIN) + @echo + @echo +endif +ifneq ($(SYSTEM_OK),true) + @false +endif diff --git a/examples/cpp/helloworld/README.md b/examples/cpp/helloworld/README.md new file mode 100644 index 0000000000..641aadd52d --- /dev/null +++ b/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](https://github.com/grpc/grpc/blob/master/INSTALL). + +### 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](examples/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. + +``` +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 + + ``` + auto channel = CreateChannel("localhost:50051", InsecureCredentials(), ChannelArguments()); + ``` + +- 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: + + ``` + auto stub = helloworld::Greeter::NewStub(channel); + ``` + +- Make a unary rpc, with `ClientContext` and request/response proto messages. + + ``` + ClientContext context; + HelloRequest request; + request.set_name("hello"); + HelloReply reply; + Status status = stub->SayHello(&context, request, &reply); + ``` + +- Check returned status and response. + + ``` + if (status.ok()) { + // check reply.message() + } else { + // rpc failed. + } + ``` + +For a working example, refer to [greeter_client.cc](examples/cpp/helloworld/greeter_client.cc). + +### Writing a server + +- Implement the service interface + + ``` + 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 + + ``` + 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](examples/cpp/helloworld/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`. + + ``` + CompletionQueue cq; + auto rpc = stub->AsyncSayHello(&context, request, &cq); + ``` + +- Ask for reply and final status, with a unique tag + + ``` + 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. + + ``` + 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](examples/cpp/helloworld/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 + + ``` + 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 + + ``` + 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. + + ``` + 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. + + ``` + 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](examples/cpp/helloworld/greeter_async_server.cc). + + + + diff --git a/examples/cpp/helloworld/greeter_async_client.cc b/examples/cpp/helloworld/greeter_async_client.cc new file mode 100644 index 0000000000..d99f89b135 --- /dev/null +++ b/examples/cpp/helloworld/greeter_async_client.cc @@ -0,0 +1,98 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <iostream> +#include <memory> +#include <string> + +#include <grpc/grpc.h> +#include <grpc/support/log.h> +#include <grpc++/channel.h> +#include <grpc++/client_context.h> +#include <grpc++/completion_queue.h> +#include <grpc++/create_channel.h> +#include <grpc++/credentials.h> +#include "helloworld.grpc.pb.h" + +using grpc::Channel; +using grpc::ChannelArguments; +using grpc::ClientAsyncResponseReader; +using grpc::ClientContext; +using grpc::CompletionQueue; +using grpc::Status; +using helloworld::HelloRequest; +using helloworld::HelloReply; +using helloworld::Greeter; + +class GreeterClient { + public: + explicit GreeterClient(std::shared_ptr<Channel> channel) + : stub_(Greeter::NewStub(channel)) {} + + std::string SayHello(const std::string& user) { + HelloRequest request; + request.set_name(user); + HelloReply reply; + ClientContext context; + CompletionQueue cq; + Status status; + + std::unique_ptr<ClientAsyncResponseReader<HelloReply> > rpc( + stub_->AsyncSayHello(&context, request, &cq)); + rpc->Finish(&reply, &status, (void*)1); + void* got_tag; + bool ok = false; + cq.Next(&got_tag, &ok); + GPR_ASSERT(ok); + GPR_ASSERT(got_tag == (void*)1); + + if (status.ok()) { + return reply.message(); + } else { + return "Rpc failed"; + } + } + + private: + std::unique_ptr<Greeter::Stub> stub_; +}; + +int main(int argc, char** argv) { + GreeterClient greeter(grpc::CreateChannel( + "localhost:50051", grpc::InsecureCredentials(), ChannelArguments())); + std::string user("world"); + std::string reply = greeter.SayHello(user); + std::cout << "Greeter received: " << reply << std::endl; + + return 0; +} diff --git a/examples/cpp/helloworld/greeter_async_server.cc b/examples/cpp/helloworld/greeter_async_server.cc new file mode 100644 index 0000000000..b8a0dbf0e2 --- /dev/null +++ b/examples/cpp/helloworld/greeter_async_server.cc @@ -0,0 +1,136 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <memory> +#include <iostream> +#include <string> +#include <thread> + +#include <grpc/grpc.h> +#include <grpc/support/log.h> +#include <grpc++/completion_queue.h> +#include <grpc++/server.h> +#include <grpc++/server_builder.h> +#include <grpc++/server_context.h> +#include <grpc++/server_credentials.h> +#include "helloworld.grpc.pb.h" + +using grpc::Server; +using grpc::ServerAsyncResponseWriter; +using grpc::ServerBuilder; +using grpc::ServerContext; +using grpc::ServerCompletionQueue; +using grpc::Status; +using helloworld::HelloRequest; +using helloworld::HelloReply; +using helloworld::Greeter; + +class ServerImpl final { + public: + ~ServerImpl() { + server_->Shutdown(); + cq_->Shutdown(); + } + + // There is no shutdown handling in this code. + void Run() { + std::string server_address("0.0.0.0:50051"); + + ServerBuilder builder; + builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); + builder.RegisterAsyncService(&service_); + cq_ = builder.AddCompletionQueue(); + server_ = builder.BuildAndStart(); + std::cout << "Server listening on " << server_address << std::endl; + + HandleRpcs(); + } + + private: + class CallData { + public: + CallData(Greeter::AsyncService* service, ServerCompletionQueue* cq) + : service_(service), cq_(cq), responder_(&ctx_), status_(CREATE) { + Proceed(); + } + + void Proceed() { + if (status_ == CREATE) { + service_->RequestSayHello(&ctx_, &request_, &responder_, cq_, cq_, + this); + status_ = PROCESS; + } else if (status_ == PROCESS) { + new CallData(service_, cq_); + std::string prefix("Hello "); + reply_.set_message(prefix + request_.name()); + responder_.Finish(reply_, Status::OK, this); + status_ = FINISH; + } else { + delete this; + } + } + + private: + Greeter::AsyncService* service_; + ServerCompletionQueue* cq_; + ServerContext ctx_; + HelloRequest request_; + HelloReply reply_; + ServerAsyncResponseWriter<HelloReply> responder_; + enum CallStatus { CREATE, PROCESS, FINISH }; + CallStatus status_; + }; + + // This can be run in multiple threads if needed. + void HandleRpcs() { + new CallData(&service_, cq_.get()); + void* tag; + bool ok; + while (true) { + cq_->Next(&tag, &ok); + GPR_ASSERT(ok); + static_cast<CallData*>(tag)->Proceed(); + } + } + + std::unique_ptr<ServerCompletionQueue> cq_; + Greeter::AsyncService service_; + std::unique_ptr<Server> server_; +}; + +int main(int argc, char** argv) { + ServerImpl server; + server.Run(); + + return 0; +} diff --git a/examples/cpp/helloworld/greeter_client.cc b/examples/cpp/helloworld/greeter_client.cc new file mode 100644 index 0000000000..dd0358ac95 --- /dev/null +++ b/examples/cpp/helloworld/greeter_client.cc @@ -0,0 +1,85 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <iostream> +#include <memory> +#include <string> + +#include <grpc/grpc.h> +#include <grpc++/channel.h> +#include <grpc++/client_context.h> +#include <grpc++/create_channel.h> +#include <grpc++/credentials.h> +#include "helloworld.grpc.pb.h" + +using grpc::Channel; +using grpc::ChannelArguments; +using grpc::ClientContext; +using grpc::Status; +using helloworld::HelloRequest; +using helloworld::HelloReply; +using helloworld::Greeter; + +class GreeterClient { + public: + GreeterClient(std::shared_ptr<Channel> channel) + : stub_(Greeter::NewStub(channel)) {} + + std::string SayHello(const std::string& user) { + HelloRequest request; + request.set_name(user); + HelloReply reply; + ClientContext context; + + Status status = stub_->SayHello(&context, request, &reply); + if (status.ok()) { + return reply.message(); + } else { + return "Rpc failed"; + } + } + + private: + std::unique_ptr<Greeter::Stub> stub_; +}; + +int main(int argc, char** argv) { + GreeterClient greeter( + grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials(), + ChannelArguments())); + std::string user("world"); + std::string reply = greeter.SayHello(user); + std::cout << "Greeter received: " << reply << std::endl; + + return 0; +} diff --git a/examples/cpp/helloworld/greeter_server.cc b/examples/cpp/helloworld/greeter_server.cc new file mode 100644 index 0000000000..c1efdf563c --- /dev/null +++ b/examples/cpp/helloworld/greeter_server.cc @@ -0,0 +1,78 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <iostream> +#include <memory> +#include <string> + +#include <grpc/grpc.h> +#include <grpc++/server.h> +#include <grpc++/server_builder.h> +#include <grpc++/server_context.h> +#include <grpc++/server_credentials.h> +#include "helloworld.grpc.pb.h" + +using grpc::Server; +using grpc::ServerBuilder; +using grpc::ServerContext; +using grpc::Status; +using helloworld::HelloRequest; +using helloworld::HelloReply; +using helloworld::Greeter; + +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; + } +}; + +void RunServer() { + std::string server_address("0.0.0.0:50051"); + GreeterServiceImpl service; + + ServerBuilder builder; + builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); + builder.RegisterService(&service); + std::unique_ptr<Server> server(builder.BuildAndStart()); + std::cout << "Server listening on " << server_address << std::endl; + server->Wait(); +} + +int main(int argc, char** argv) { + RunServer(); + + return 0; +} |