1 /*
2 *
3 * Copyright 2024 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <grpc/grpc.h>
20 #include <grpcpp/ext/proto_server_reflection_plugin.h>
21 #include <grpcpp/grpcpp.h>
22
23 #include <cstddef>
24 #include <ostream>
25 #include <string>
26
27 #include "absl/flags/flag.h"
28 #include "absl/flags/parse.h"
29
30 #ifdef BAZEL_BUILD
31 #include "examples/protos/helloworld.grpc.pb.h"
32 #else
33 #include "helloworld.grpc.pb.h"
34 #endif
35
36 ABSL_FLAG(std::string, target, "localhost:50051", "Server address");
37
38 using grpc::CallbackServerContext;
39 using grpc::Channel;
40 using grpc::ClientContext;
41 using grpc::Server;
42 using grpc::ServerBuilder;
43 using grpc::ServerUnaryReactor;
44 using grpc::Status;
45 using helloworld::Greeter;
46 using helloworld::HelloReply;
47 using helloworld::HelloRequest;
48
49 namespace {
50
51 // Sends requests as quickly as possible and times how long it takes to perform
52 // the write operation.
53 class GreeterClientReactor final
54 : public grpc::ClientBidiReactor<helloworld::HelloRequest,
55 helloworld::HelloReply> {
56 public:
GreeterClientReactor(int reqs,size_t req_size)57 explicit GreeterClientReactor(int reqs, size_t req_size) : reqs_(reqs) {
58 req_.set_name(std::string(req_size, '*'));
59 }
60
Start()61 void Start() {
62 absl::MutexLock lock(&mu_);
63 StartCall();
64 Write();
65 }
66
~GreeterClientReactor()67 ~GreeterClientReactor() override {
68 absl::MutexLock lock(&mu_);
69 mu_.Await(absl::Condition(+[](bool* done) { return *done; }, &done_));
70 }
71
OnWriteDone(bool ok)72 void OnWriteDone(bool ok) override {
73 absl::MutexLock lock(&mu_);
74 std::cout << "Writing took " << absl::Now() - *time_ << std::endl;
75 time_ = absl::nullopt;
76 if (ok) {
77 Write();
78 }
79 }
80
OnDone(const grpc::Status & status)81 void OnDone(const grpc::Status& status) override {
82 if (status.ok()) {
83 std::cout << "Done\n";
84 } else {
85 std::cout << "Done with error: [" << status.error_code() << "] "
86 << status.error_message() << "\n";
87 }
88 absl::MutexLock lock(&mu_);
89 done_ = true;
90 }
91
92 private:
Write()93 void Write() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&mu_) {
94 if (reqs_ == 0) {
95 StartWritesDone();
96 return;
97 }
98 --reqs_;
99 StartWrite(&req_);
100 time_ = absl::Now();
101 }
102
103 absl::Mutex mu_;
104 bool done_ ABSL_GUARDED_BY(&mu_) = false;
105 HelloRequest req_;
106 size_t reqs_;
107 absl::optional<absl::Time> time_ ABSL_GUARDED_BY(mu_);
108 };
109
110 } // namespace
111
main(int argc,char ** argv)112 int main(int argc, char** argv) {
113 absl::ParseCommandLine(argc, argv);
114 grpc::ChannelArguments channel_arguments;
115 auto channel = grpc::CreateCustomChannel(absl::GetFlag(FLAGS_target),
116 grpc::InsecureChannelCredentials(),
117 channel_arguments);
118 auto stub = Greeter::NewStub(channel);
119 // Send 10 requests with 3Mb payload. This will eventually fill the buffer
120 // and make
121 GreeterClientReactor reactor(10, 3 * 1024 * 1024);
122 grpc::ClientContext context;
123 stub->async()->SayHelloBidiStream(&context, &reactor);
124 reactor.Start();
125 return 0;
126 }
127