diff --git a/examples/cpp/reflection/BUILD b/examples/cpp/reflection/BUILD new file mode 100644 index 00000000000..44bc74db88f --- /dev/null +++ b/examples/cpp/reflection/BUILD @@ -0,0 +1,28 @@ +# Copyright 2023 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +licenses(["notice"]) + +cc_binary( + name = "reflection_server", + srcs = ["reflection_server.cc"], + deps = [ + "//:grpc++", + "//:grpc++_reflection", + "//examples/protos:helloworld_cc_grpc", + "@com_google_absl//absl/flags:flag", + "@com_google_absl//absl/flags:parse", + "@com_google_absl//absl/strings:str_format", + ], +) diff --git a/examples/cpp/reflection/README.md b/examples/cpp/reflection/README.md new file mode 100644 index 00000000000..8767d66fc6a --- /dev/null +++ b/examples/cpp/reflection/README.md @@ -0,0 +1,18 @@ +gRPC Reflection Example +================ + +This example shows how reflection can be registered on a gRPC server. + +### Build and run the example + +To start the reflection server on its default port of 50051, run the following command from within the `examples/cpp/reflection` folder: + +``` +$ bazel run :reflection_server +``` + +There are multiple existing reflection clients you can use to inspect its services. + +To use `gRPC CLI`, see https://github.com/grpc/grpc-go/blob/master/Documentation/server-reflection-tutorial.md#grpc-cli. + +To use `grpcurl`, see https://github.com/fullstorydev/grpcurl. diff --git a/examples/cpp/reflection/reflection_server.cc b/examples/cpp/reflection/reflection_server.cc new file mode 100644 index 00000000000..8ef327bbee8 --- /dev/null +++ b/examples/cpp/reflection/reflection_server.cc @@ -0,0 +1,74 @@ +// Copyright 2023 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "absl/flags/flag.h" +#include "absl/flags/parse.h" +#include "absl/strings/str_format.h" +#include "examples/protos/helloworld.grpc.pb.h" + +#include +#include + +using grpc::CallbackServerContext; +using grpc::Server; +using grpc::ServerBuilder; +using grpc::ServerUnaryReactor; +using grpc::Status; +using helloworld::Greeter; +using helloworld::HelloReply; +using helloworld::HelloRequest; + +ABSL_FLAG(uint16_t, port, 50051, "Server port for the service"); + +// Logic and data behind the server's behavior. +class GreeterServiceImpl final : public Greeter::CallbackService { + ServerUnaryReactor* SayHello(CallbackServerContext* context, + const HelloRequest* request, + HelloReply* reply) override { + std::string prefix("Hello "); + reply->set_message(prefix + request->name()); + + ServerUnaryReactor* reactor = context->DefaultReactor(); + reactor->Finish(Status::OK); + return reactor; + } +}; + +void RunServer(uint16_t port) { + std::string server_address = absl::StrFormat("0.0.0.0:%d", port); + GreeterServiceImpl service; + + grpc::reflection::InitProtoReflectionServerBuilderPlugin(); + ServerBuilder builder; + // Listen on the given address without any authentication mechanism. + builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); + // Register "service" as the instance through which we'll communicate with + // clients. In this case it corresponds to an *synchronous* service. + builder.RegisterService(&service); + // Finally assemble the server. + std::unique_ptr server(builder.BuildAndStart()); + std::cout << "Server listening on " << server_address << '\n'; + + // Wait for the server to shutdown. Note that some other thread must be + // responsible for shutting down the server for this call to ever return. + server->Wait(); +} + +int main(int argc, char** argv) { + absl::ParseCommandLine(argc, argv); + RunServer(absl::GetFlag(FLAGS_port)); + return 0; +}