/* * Copyright 2014 Google Inc. All rights reserved. * * 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 "monster_test_generated.h" #include "monster_test.grpc.fb.h" using namespace MyGame::Example; // The callback implementation of our server, that derives from the generated // code. It implements all rpcs specified in the FlatBuffers schema. class ServiceImpl final : public MyGame::Example::MonsterStorage::Service { virtual ::grpc::Status Store(::grpc::ServerContext* context, const flatbuffers::BufferRef *request, flatbuffers::BufferRef *response) override { // Create a response from the incoming request name. fbb_.Clear(); auto stat_offset = CreateStat(fbb_, fbb_.CreateString("Hello, " + request->GetRoot()->name()->str())); fbb_.Finish(stat_offset); // Since we keep reusing the same FlatBufferBuilder, the memory it owns // remains valid until the next call (this BufferRef doesn't own the // memory it points to). *response = flatbuffers::BufferRef(fbb_.GetBufferPointer(), fbb_.GetSize()); return grpc::Status::OK; } virtual ::grpc::Status Retrieve(::grpc::ServerContext *context, const flatbuffers::BufferRef *request, ::grpc::ServerWriter< flatbuffers::BufferRef>* writer) override { assert(false); // We're not actually using this RPC. return grpc::Status::CANCELLED; } private: flatbuffers::FlatBufferBuilder fbb_; }; // Track the server instance, so we can terminate it later. grpc::Server *server_instance = nullptr; // Mutex to protec this variable. std::mutex wait_for_server; std::condition_variable server_instance_cv; // This function implements the server thread. void RunServer() { auto server_address = "0.0.0.0:50051"; // Callback interface we implemented above. ServiceImpl service; grpc::ServerBuilder builder; builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); builder.RegisterService(&service); // Start the server. Lock to change the variable we're changing. wait_for_server.lock(); server_instance = builder.BuildAndStart().release(); wait_for_server.unlock(); server_instance_cv.notify_one(); std::cout << "Server listening on " << server_address << std::endl; // This will block the thread and serve requests. server_instance->Wait(); } int main(int /*argc*/, const char * /*argv*/[]) { // Launch server. std::thread server_thread(RunServer); // wait for server to spin up. std::unique_lock lock(wait_for_server); while (!server_instance) server_instance_cv.wait(lock); // Now connect the client. auto channel = grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials()); auto stub = MyGame::Example::MonsterStorage::NewStub(channel); grpc::ClientContext context; // Build a request with the name set. flatbuffers::FlatBufferBuilder fbb; auto monster_offset = CreateMonster(fbb, 0, 0, 0, fbb.CreateString("Fred")); fbb.Finish(monster_offset); auto request = flatbuffers::BufferRef(fbb.GetBufferPointer(), fbb.GetSize()); flatbuffers::BufferRef response; // The actual RPC. auto status = stub->Store(&context, request, &response); if (status.ok()) { auto resp = response.GetRoot()->id(); std::cout << "RPC response: " << resp->str() << std::endl; } else { std::cout << "RPC failed" << std::endl; } server_instance->Shutdown(); server_thread.join(); delete server_instance; return 0; }