From 7a5a9544ef9afb8456e5241741ceb387153bfb38 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 9 Jan 2019 14:56:42 -0800 Subject: Add a naive client server implementation --- examples/BUILD | 14 ++++ examples/cpp/keyvaluestore/caching_interceptor.cc | 0 examples/cpp/keyvaluestore/client.cc | 85 +++++++++++++++++++ examples/cpp/keyvaluestore/server.cc | 99 +++++++++++++++++++++++ 4 files changed, 198 insertions(+) create mode 100644 examples/cpp/keyvaluestore/caching_interceptor.cc create mode 100644 examples/cpp/keyvaluestore/client.cc create mode 100644 examples/cpp/keyvaluestore/server.cc diff --git a/examples/BUILD b/examples/BUILD index b6cb9d48d3..4fee663bd9 100644 --- a/examples/BUILD +++ b/examples/BUILD @@ -98,3 +98,17 @@ cc_binary( defines = ["BAZEL_BUILD"], deps = [":helloworld", "//:grpc++"], ) + +cc_binary( + name = "keyvaluestore_client", + srcs = ["cpp/keyvaluestore/client.cc"], + defines = ["BAZEL_BUILD"], + deps = [":keyvaluestore", "//:grpc++"], +) + +cc_binary( + name = "keyvaluestore_server", + srcs = ["cpp/keyvaluestore/server.cc"], + defines = ["BAZEL_BUILD"], + deps = [":keyvaluestore", "//:grpc++"], +) \ No newline at end of file diff --git a/examples/cpp/keyvaluestore/caching_interceptor.cc b/examples/cpp/keyvaluestore/caching_interceptor.cc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/cpp/keyvaluestore/client.cc b/examples/cpp/keyvaluestore/client.cc new file mode 100644 index 0000000000..9f5fa37cb1 --- /dev/null +++ b/examples/cpp/keyvaluestore/client.cc @@ -0,0 +1,85 @@ +/* + * + * Copyright 2018 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 +#include +#include +#include + +#include + +#ifdef BAZEL_BUILD +#include "examples/protos/keyvaluestore.grpc.pb.h" +#else +#include "keyvaluestore.grpc.pb.h" +#endif + +using grpc::Channel; +using grpc::ClientContext; +using grpc::Status; +using keyvaluestore::Request; +using keyvaluestore::Response; +using keyvaluestore::KeyValueStore; + +class KeyValueStoreClient { + public: + KeyValueStoreClient(std::shared_ptr channel) + : stub_(KeyValueStore::NewStub(channel)) {} + + // Assembles the client's payload, sends it and presents the response back + // from the server. + void GetValues(const std::vector& keys) { + // Context for the client. It could be used to convey extra information to + // the server and/or tweak certain RPC behaviors. + ClientContext context; + auto stream = stub_->GetValues(&context); + for (const auto& key:keys) { + // Data we are sending to the server. + Request request; + request.set_key(key); + stream->Write(request); + + Response response; + stream->Read(&response); + std::cout << key << " : " << response.value() << "\n"; + } + stream->WritesDone(); + Status status = stream->Finish(); + if(!status.ok()) { + std::cout << status.error_code() << ": " << status.error_message() + << std::endl; + std::cout << "RPC failed"; + } + } + + private: + std::unique_ptr stub_; +}; + +int main(int argc, char** argv) { + // Instantiate the client. It requires a channel, out of which the actual RPCs + // are created. This channel models a connection to an endpoint (in this case, + // localhost at port 50051). We indicate that the channel isn't authenticated + // (use of InsecureChannelCredentials()). + KeyValueStoreClient client(grpc::CreateChannel( + "localhost:50051", grpc::InsecureChannelCredentials())); + std::vector keys = {"key1", "key2", "key3", "key4", "key5"}; + client.GetValues(keys); + + return 0; +} diff --git a/examples/cpp/keyvaluestore/server.cc b/examples/cpp/keyvaluestore/server.cc new file mode 100644 index 0000000000..75d30eb1f8 --- /dev/null +++ b/examples/cpp/keyvaluestore/server.cc @@ -0,0 +1,99 @@ +/* + * + * Copyright 2018 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 +#include +#include +#include + +#include + +#ifdef BAZEL_BUILD +#include "examples/protos/keyvaluestore.grpc.pb.h" +#else +#include "keyvaluestore.grpc.pb.h" +#endif + +using grpc::Server; +using grpc::ServerBuilder; +using grpc::ServerContext; +using grpc::ServerReaderWriter; +using grpc::Status; +using keyvaluestore::Request; +using keyvaluestore::Response; +using keyvaluestore::KeyValueStore; + +struct kv_pair { + const char* key; + const char* value; +}; + +static const kv_pair kvs_map[] = { + {"key1", "value1"}, + {"key2", "value2"}, + {"key3", "value3"}, + {"key4", "value4"}, + {"key5", "value5"}, +}; + +const char * get_value_from_map(const char* key) { + for(size_t i = 0; i < sizeof(kvs_map) / sizeof(kv_pair); ++i) { + if(strcmp(key, kvs_map[i].key) == 0) { + return kvs_map[i].value; + } + } + return nullptr; +} + +// Logic and data behind the server's behavior. +class KeyValueStoreServiceImpl final : public KeyValueStore::Service { + Status GetValues(ServerContext* context, ServerReaderWriter *stream) override { + Request request; + while(stream->Read(&request)) { + Response response; + response.set_value(get_value_from_map(request.key().c_str())); + stream->Write(response); + } + return Status::OK; + } +}; + +void RunServer() { + std::string server_address("0.0.0.0:50051"); + KeyValueStoreServiceImpl service; + + ServerBuilder builder; + // Listen on the given address without any authentication mechanism. + builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); + // Register "service" as the instance through which we'll communicate with + // clients. In this case it corresponds to an *synchronous* service. + builder.RegisterService(&service); + // Finally assemble the server. + std::unique_ptr server(builder.BuildAndStart()); + std::cout << "Server listening on " << server_address << std::endl; + + // Wait for the server to shutdown. Note that some other thread must be + // responsible for shutting down the server for this call to ever return. + server->Wait(); +} + +int main(int argc, char** argv) { + RunServer(); + + return 0; +} -- cgit v1.2.3 From f1e9306c702ee83f4808597212824301d3a909a5 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 10 Jan 2019 13:22:37 -0800 Subject: return empty string instead of nullptr --- examples/cpp/keyvaluestore/server.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/cpp/keyvaluestore/server.cc b/examples/cpp/keyvaluestore/server.cc index 75d30eb1f8..8dc8752eda 100644 --- a/examples/cpp/keyvaluestore/server.cc +++ b/examples/cpp/keyvaluestore/server.cc @@ -57,7 +57,7 @@ const char * get_value_from_map(const char* key) { return kvs_map[i].value; } } - return nullptr; + return ""; } // Logic and data behind the server's behavior. -- cgit v1.2.3 From c01e866a88beee6143f19fa243b85d5792c36cae Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 10 Jan 2019 13:25:57 -0800 Subject: better documentation --- examples/cpp/keyvaluestore/client.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/cpp/keyvaluestore/client.cc b/examples/cpp/keyvaluestore/client.cc index 9f5fa37cb1..cdf353fafd 100644 --- a/examples/cpp/keyvaluestore/client.cc +++ b/examples/cpp/keyvaluestore/client.cc @@ -41,19 +41,19 @@ class KeyValueStoreClient { KeyValueStoreClient(std::shared_ptr channel) : stub_(KeyValueStore::NewStub(channel)) {} - // Assembles the client's payload, sends it and presents the response back - // from the server. + // Requests each key in the vector and displays the value as a pair void GetValues(const std::vector& keys) { // Context for the client. It could be used to convey extra information to // the server and/or tweak certain RPC behaviors. ClientContext context; auto stream = stub_->GetValues(&context); for (const auto& key:keys) { - // Data we are sending to the server. + // Key we are sending to the server. Request request; request.set_key(key); stream->Write(request); + // Get the value for the sent key Response response; stream->Read(&response); std::cout << key << " : " << response.value() << "\n"; -- cgit v1.2.3 From aa5950936923437b45dbe75f5d981033ec00a2f9 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 10 Jan 2019 14:13:43 -0800 Subject: Reviewer comments --- examples/cpp/keyvaluestore/caching_interceptor.cc | 0 examples/cpp/keyvaluestore/client.cc | 3 ++- examples/cpp/keyvaluestore/server.cc | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) delete mode 100644 examples/cpp/keyvaluestore/caching_interceptor.cc diff --git a/examples/cpp/keyvaluestore/caching_interceptor.cc b/examples/cpp/keyvaluestore/caching_interceptor.cc deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/examples/cpp/keyvaluestore/client.cc b/examples/cpp/keyvaluestore/client.cc index cdf353fafd..e956a16573 100644 --- a/examples/cpp/keyvaluestore/client.cc +++ b/examples/cpp/keyvaluestore/client.cc @@ -41,7 +41,8 @@ class KeyValueStoreClient { KeyValueStoreClient(std::shared_ptr channel) : stub_(KeyValueStore::NewStub(channel)) {} - // Requests each key in the vector and displays the value as a pair + // Requests each key in the vector and displays the key and its corresponding + // value as a pair void GetValues(const std::vector& keys) { // Context for the client. It could be used to convey extra information to // the server and/or tweak certain RPC behaviors. diff --git a/examples/cpp/keyvaluestore/server.cc b/examples/cpp/keyvaluestore/server.cc index 8dc8752eda..515a1ba4c9 100644 --- a/examples/cpp/keyvaluestore/server.cc +++ b/examples/cpp/keyvaluestore/server.cc @@ -81,7 +81,7 @@ void RunServer() { // Listen on the given address without any authentication mechanism. builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); // Register "service" as the instance through which we'll communicate with - // clients. In this case it corresponds to an *synchronous* service. + // clients. In this case, it corresponds to an *synchronous* service. builder.RegisterService(&service); // Finally assemble the server. std::unique_ptr server(builder.BuildAndStart()); -- cgit v1.2.3 From b72bb30126b8baf8b8140266bad2009e6d3c4ded Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 10 Jan 2019 14:18:24 -0800 Subject: Clang format --- examples/cpp/keyvaluestore/client.cc | 8 ++++---- examples/cpp/keyvaluestore/server.cc | 20 +++++++++----------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/examples/cpp/keyvaluestore/client.cc b/examples/cpp/keyvaluestore/client.cc index e956a16573..17e407c273 100644 --- a/examples/cpp/keyvaluestore/client.cc +++ b/examples/cpp/keyvaluestore/client.cc @@ -32,9 +32,9 @@ using grpc::Channel; using grpc::ClientContext; using grpc::Status; +using keyvaluestore::KeyValueStore; using keyvaluestore::Request; using keyvaluestore::Response; -using keyvaluestore::KeyValueStore; class KeyValueStoreClient { public: @@ -48,7 +48,7 @@ class KeyValueStoreClient { // the server and/or tweak certain RPC behaviors. ClientContext context; auto stream = stub_->GetValues(&context); - for (const auto& key:keys) { + for (const auto& key : keys) { // Key we are sending to the server. Request request; request.set_key(key); @@ -61,7 +61,7 @@ class KeyValueStoreClient { } stream->WritesDone(); Status status = stream->Finish(); - if(!status.ok()) { + if (!status.ok()) { std::cout << status.error_code() << ": " << status.error_message() << std::endl; std::cout << "RPC failed"; @@ -79,7 +79,7 @@ int main(int argc, char** argv) { // (use of InsecureChannelCredentials()). KeyValueStoreClient client(grpc::CreateChannel( "localhost:50051", grpc::InsecureChannelCredentials())); - std::vector keys = {"key1", "key2", "key3", "key4", "key5"}; + std::vector keys = {"key1", "key2", "key3", "key4", "key5"}; client.GetValues(keys); return 0; diff --git a/examples/cpp/keyvaluestore/server.cc b/examples/cpp/keyvaluestore/server.cc index 515a1ba4c9..e75da9c62d 100644 --- a/examples/cpp/keyvaluestore/server.cc +++ b/examples/cpp/keyvaluestore/server.cc @@ -34,9 +34,9 @@ using grpc::ServerBuilder; using grpc::ServerContext; using grpc::ServerReaderWriter; using grpc::Status; +using keyvaluestore::KeyValueStore; using keyvaluestore::Request; using keyvaluestore::Response; -using keyvaluestore::KeyValueStore; struct kv_pair { const char* key; @@ -44,16 +44,13 @@ struct kv_pair { }; static const kv_pair kvs_map[] = { - {"key1", "value1"}, - {"key2", "value2"}, - {"key3", "value3"}, - {"key4", "value4"}, - {"key5", "value5"}, + {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}, + {"key4", "value4"}, {"key5", "value5"}, }; -const char * get_value_from_map(const char* key) { - for(size_t i = 0; i < sizeof(kvs_map) / sizeof(kv_pair); ++i) { - if(strcmp(key, kvs_map[i].key) == 0) { +const char* get_value_from_map(const char* key) { + for (size_t i = 0; i < sizeof(kvs_map) / sizeof(kv_pair); ++i) { + if (strcmp(key, kvs_map[i].key) == 0) { return kvs_map[i].value; } } @@ -62,9 +59,10 @@ const char * get_value_from_map(const char* key) { // Logic and data behind the server's behavior. class KeyValueStoreServiceImpl final : public KeyValueStore::Service { - Status GetValues(ServerContext* context, ServerReaderWriter *stream) override { + Status GetValues(ServerContext* context, + ServerReaderWriter* stream) override { Request request; - while(stream->Read(&request)) { + while (stream->Read(&request)) { Response response; response.set_value(get_value_from_map(request.key().c_str())); stream->Write(response); -- cgit v1.2.3