xref: /aosp_15_r20/external/grpc-grpc/examples/cpp/generic_api/greeter_client.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1  // Copyright 2023 gRPC authors.
2  //
3  // Licensed under the Apache License, Version 2.0 (the "License");
4  // you may not use this file except in compliance with the License.
5  // You may obtain a copy of the License at
6  //
7  //     http://www.apache.org/licenses/LICENSE-2.0
8  //
9  // Unless required by applicable law or agreed to in writing, software
10  // distributed under the License is distributed on an "AS IS" BASIS,
11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  // See the License for the specific language governing permissions and
13  // limitations under the License.
14  
15  #include <condition_variable>
16  #include <iostream>
17  #include <memory>
18  #include <mutex>
19  #include <string>
20  
21  #include "absl/flags/flag.h"
22  #include "absl/flags/parse.h"
23  #include "absl/strings/str_format.h"
24  
25  #include <grpcpp/generic/generic_stub.h>
26  #include <grpcpp/grpcpp.h>
27  
28  #ifdef BAZEL_BUILD
29  #include "examples/protos/helloworld.grpc.pb.h"
30  #else
31  #include "helloworld.grpc.pb.h"
32  #endif
33  
34  ABSL_FLAG(std::string, target, "localhost:50051", "Server address");
35  
36  using grpc::Channel;
37  using grpc::ClientContext;
38  using grpc::Status;
39  using helloworld::Greeter;
40  using helloworld::HelloReply;
41  using helloworld::HelloRequest;
42  
43  using ProtoGenericStub =
44      ::grpc::TemplatedGenericStub<::google::protobuf::Message,
45                                   ::google::protobuf::Message>;
46  
47  class GreeterClient {
48   public:
GreeterClient(std::shared_ptr<Channel> channel)49    GreeterClient(std::shared_ptr<Channel> channel)
50        : stub_(new ProtoGenericStub(channel)) {}
51  
52    // Assembles the client's payload, sends it and prints the response back
53    // from the server.
SayHello(const std::string & user)54    void SayHello(const std::string& user) {
55      // Data we are sending to the server.
56      HelloRequest request;
57      request.set_name(user);
58      // Container for the data we expect from the server.
59      HelloReply reply;
60      // Context for the client. It could be used to convey extra information to
61      // the server and/or tweak certain RPC behaviors.
62      ClientContext context;
63      // The actual RPC.
64      std::mutex mu;
65      std::condition_variable cv;
66      bool done = false;
67      Status status;
68      std::cout << absl::StrFormat("### Send: SayHello(name=%s)", user)
69                << std::endl;
70      // Send a unary call using a generic stub. Unlike generated subs,
71      // this requires to specify the name of call.
72      stub_->UnaryCall(&context, "/helloworld.Greeter/SayHello",
73                       grpc::StubOptions(), &request, &reply, [&](Status s) {
74                         status = std::move(s);
75                         std::lock_guard<std::mutex> lock(mu);
76                         done = true;
77                         cv.notify_one();
78                       });
79      std::unique_lock<std::mutex> lock(mu);
80      while (!done) {
81        cv.wait(lock);
82      }
83      // Handles the reply
84      if (status.ok()) {
85        std::cout << absl::StrFormat("Ok. ReplyMessage=%s", reply.message())
86                  << std::endl;
87      } else {
88        std::cout << absl::StrFormat("Failed. Code=%d Message=%s",
89                                     status.error_code(), status.error_message())
90                  << std::endl;
91      }
92    }
93  
94   private:
95    // Instead of `Greeter::Stub`, it uses `ProtoGenericStub` to send any calls.
96    std::unique_ptr<ProtoGenericStub> stub_;
97  };
98  
main(int argc,char ** argv)99  int main(int argc, char** argv) {
100    absl::ParseCommandLine(argc, argv);
101    // Instantiate the client. It requires a channel, out of which the actual RPCs
102    // are created. This channel models a connection to an endpoint specified by
103    // the argument "--target=" which is the only expected argument.
104    std::string target_str = absl::GetFlag(FLAGS_target);
105    // We indicate that the channel isn't authenticated (use of
106    // InsecureChannelCredentials()).
107    GreeterClient greeter(
108        grpc::CreateChannel(target_str, grpc::InsecureChannelCredentials()));
109    greeter.SayHello("World");
110    greeter.SayHello("gRPC");
111    return 0;
112  }
113