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 <grpcpp/grpcpp.h>
16
17 #include <condition_variable>
18 #include <iostream>
19 #include <memory>
20 #include <mutex>
21 #include <string>
22 #include <vector>
23
24 #include "absl/flags/flag.h"
25 #include "absl/flags/parse.h"
26 #include "absl/strings/str_cat.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 grpc::StatusCode;
40 using helloworld::Greeter;
41 using helloworld::HelloReply;
42 using helloworld::HelloRequest;
43
44 // Requests each key in the vector and displays the key and its corresponding
45 // value as a pair.
46 class KeyValueStoreClient
47 : public grpc::ClientBidiReactor<HelloRequest, HelloReply> {
48 public:
KeyValueStoreClient(std::shared_ptr<Channel> channel)49 KeyValueStoreClient(std::shared_ptr<Channel> channel)
50 : stub_(Greeter::NewStub(channel)) {
51 stub_->async()->SayHelloBidiStream(&context_, this);
52 request_.set_name("Begin");
53 StartWrite(&request_);
54 StartCall();
55 }
56
OnReadDone(bool ok)57 void OnReadDone(bool ok) override {
58 if (ok) {
59 std::cout << request_.name() << " : " << response_.message() << std::endl;
60 if (++counter_ < 10) {
61 request_.set_name(absl::StrCat("Count ", counter_));
62 StartWrite(&request_);
63 } else {
64 // Cancel after sending 10 messages
65 context_.TryCancel();
66 }
67 }
68 }
69
OnWriteDone(bool ok)70 void OnWriteDone(bool ok) override {
71 if (ok) {
72 StartRead(&response_);
73 }
74 }
75
OnDone(const grpc::Status & status)76 void OnDone(const grpc::Status& status) override {
77 if (!status.ok()) {
78 if (status.error_code() == StatusCode::CANCELLED) {
79 // Eventually client will know here that call is cancelled.
80 std::cout << "RPC Cancelled!" << std::endl;
81 } else {
82 std::cout << "RPC Failed: " << status.error_code() << ": "
83 << status.error_message() << std::endl;
84 }
85 }
86 std::unique_lock<std::mutex> l(mu_);
87 done_ = true;
88 cv_.notify_all();
89 }
90
Await()91 void Await() {
92 std::unique_lock<std::mutex> l(mu_);
93 while (!done_) {
94 cv_.wait(l);
95 }
96 }
97
98 private:
99 std::unique_ptr<Greeter::Stub> stub_;
100 size_t counter_ = 0;
101 ClientContext context_;
102 bool done_ = false;
103 HelloRequest request_;
104 HelloReply response_;
105 std::mutex mu_;
106 std::condition_variable cv_;
107 };
108
main(int argc,char ** argv)109 int main(int argc, char** argv) {
110 absl::ParseCommandLine(argc, argv);
111 // Instantiate the client. It requires a channel, out of which the actual RPCs
112 // are created. This channel models a connection to an endpoint specified by
113 // the argument "--target=" which is the only expected argument.
114 std::string target_str = absl::GetFlag(FLAGS_target);
115 KeyValueStoreClient client(
116 grpc::CreateChannel(target_str, grpc::InsecureChannelCredentials()));
117 client.Await();
118 return 0;
119 }
120