• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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