//and this is client code
/*
*
* Copyright 2021 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 <chrono>
#include <condition_variable>
#include <iostream>
#include <memory>
#include <mutex>
#include <random>
#include <string>
#include <thread>
#include "helper.h"
#include <grpc/grpc.h>
#include <grpcpp/alarm.h>
#include <grpcpp/channel.h>
#include <grpcpp/client_context.h>
#include <grpcpp/create_channel.h>
#include <grpcpp/security/credentials.h>
#ifdef BAZEL_BUILD
#include "examples/protos/route_guide.grpc.pb.h"
#else
#include "route_guide.grpc.pb.h"
#endif
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using routeguide::Feature;
using routeguide::Point;
using routeguide::Rectangle;
using routeguide::RouteGuide;
using routeguide::RouteNote;
using routeguide::RouteSummary;
Point MakePoint(long latitude, long longitude) {
Point p;
p.set_latitude(latitude);
p.set_longitude(longitude);
return p;
}
Feature MakeFeature(const std::string& name, long latitude, long longitude)
{
Feature f;
f.set_name(name);
f.mutable_location()->CopyFrom(MakePoint(latitude, longitude));
return f;
}
RouteNote MakeRouteNote(const std::string& message, long latitude,
long longitude) {
RouteNote n;
n.set_message(message);
n.mutable_location()->CopyFrom(MakePoint(latitude, longitude));
return n;
}
class RouteGuideClient {
public:
RouteGuideClient(std::shared_ptr<Channel> channel, const std::string& db)
: stub_(RouteGuide::NewStub(channel)) {
routeguide::ParseDb(db, &feature_list_);
}
void RouteChat() {
class Chatter : public grpc::ClientBidiReactor<RouteNote, RouteNote> {
public:
explicit Chatter(RouteGuide::Stub* stub)
: notes_{MakeRouteNote("First message", 0, 0),
MakeRouteNote("Second message", 0, 1),
MakeRouteNote("Third message", 1, 0),
MakeRouteNote("Fourth message", 0, 0)},
notes_iterator_(notes_.begin()) {
stub->async()->RouteChat(&context_, this);
NextWrite();
StartRead(&server_note_);
StartCall();
}
void OnWriteDone(bool /*ok*/) override { NextWrite(); }
void OnReadDone(bool ok) override {
if (ok) {
std::cout << "Got message " << server_note_.message() << " at "
<< server_note_.location().latitude() << ", "
<< server_note_.location().longitude() << std::endl;
StartRead(&server_note_);
}
}
void OnDone(const Status& s) override {
std::unique_lock<std::mutex> l(mu_);
status_ = s;
done_ = true;
cv_.notify_one();
}
Status Await() {
std::unique_lock<std::mutex> l(mu_);
cv_.wait(l, [this] { return done_; });
return std::move(status_);
}
private:
void NextWrite() {
if (notes_iterator_ != notes_.end()) {
const auto& note = *notes_iterator_;
std::cout << "Sending message " << note.message() << " at "
<< note.location().latitude() << ", "
<< note.location().longitude() << std::endl;
StartWrite(¬e);
notes_iterator_++;
} else {
StartWritesDone();
}
}
ClientContext context_;
const std::vector<RouteNote> notes_;
std::vector<RouteNote>::const_iterator notes_iterator_;
RouteNote server_note_;
std::mutex mu_;
std::condition_variable cv_;
Status status_;
bool done_ = false;
};
Chatter chatter(stub_.get());
Status status = chatter.Await();
if (!status.ok()) {
std::cout << "RouteChat rpc failed." << std::endl;
}
}
private:
const float kCoordFactor_ = 10000000.0;
std::unique_ptr<RouteGuide::Stub> stub_;
std::vector<Feature> feature_list_;
};
int main(int argc, char** argv) {
// Expect only arg: --db_path=path/to/route_guide_db.json.
std::string db = routeguide::GetDbFileContent(argc, argv);
RouteGuideClient guide(
grpc::CreateChannel("localhost:50051",
grpc::InsecureChannelCredentials()),
db);
std::cout << "-------------- RouteChat --------------" << std::endl;
guide.RouteChat();
return 0;
}
среда, 22 марта 2023 г. в 01:42:07 UTC+3, Dmitry Gorelov:
> Oh man, it is not working even with *one *client! same problem in
> proto_utils.h
>
>
> среда, 22 марта 2023 г. в 01:12:55 UTC+3, Dmitry Gorelov:
>
>> Hi All,
>>
>> please help to modify this peace of server code for bidirectional stream
>> in order to make it work correclty with *multiple clients* at one time.
>> Currently it crashes with segmentation fault in the proto_utils.h.
>>
>> class RouteGuideImpl final : public RouteGuide::CallbackService {
>> public:
>> explicit RouteGuideImpl(const std::string& db) {
>> routeguide::ParseDb(db, &feature_list_);
>> }
>>
>> grpc::ServerBidiReactor<RouteNote, RouteNote>* RouteChat(
>> CallbackServerContext* context) override {
>> class Chatter : public grpc::ServerBidiReactor<RouteNote, RouteNote> {
>> public:
>> Chatter(absl::Mutex* mu, std::vector<RouteNote>* received_notes)
>> : mu_(mu), received_notes_(received_notes) {
>> StartRead(¬e_);
>> }
>>
>> void OnDone() override { delete this; }
>> void OnReadDone(bool ok) override {
>> if (ok) {
>> // Unlike the other example in this directory that's not using
>> // the reactor pattern, we can't grab a local lock to secure the
>> // access to the notes vector, because the reactor will most
>> likely
>> // make us jump threads, so we'll have to use a different
>> locking
>> // strategy. We'll grab the lock locally to build a copy of the
>> // list of nodes we're going to send, then we'll grab the lock
>> // again to append the received note to the existing vector.
>> mu_->Lock();
>> std::copy_if(received_notes_->begin(), received_notes_->end(),
>> std::back_inserter(to_send_notes_),
>> [this](const RouteNote& note) {
>> return note.location().latitude() ==
>> note_.location().latitude() &&
>> note.location().longitude() ==
>> note_.location().longitude();
>> });
>> mu_->Unlock();
>> notes_iterator_ = to_send_notes_.begin();
>> NextWrite();
>> } else {
>> std::cout << "some client finished" << std::endl;
>> Finish(Status::OK);
>> }
>> }
>> void OnWriteDone(bool /*ok*/) override { NextWrite(); }
>>
>> private:
>> void NextWrite() {
>> if (notes_iterator_ != to_send_notes_.end()) {
>> StartWrite(&*notes_iterator_);
>> notes_iterator_++;
>> } else {
>> mu_->Lock();
>> received_notes_->push_back(note_);
>> mu_->Unlock();
>> StartRead(¬e_);
>> }
>> }
>> RouteNote note_;
>> absl::Mutex* mu_;
>> std::vector<RouteNote>* received_notes_;
>> std::vector<RouteNote> to_send_notes_;
>> std::vector<RouteNote>::iterator notes_iterator_;
>> };
>> return new Chatter(&mu_, &received_notes_);
>> }
>>
>> private:
>> std::vector<Feature> feature_list_;
>> absl::Mutex mu_;
>> std::vector<RouteNote> received_notes_ ABSL_GUARDED_BY(mu_);
>> };
>>
>
--
You received this message because you are subscribed to the Google Groups
"grpc.io" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/grpc-io/aacf744f-c83b-4b0a-94e7-5dff55a12b21n%40googlegroups.com.