| /* |
| * 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 <thread> |
| |
| #include <grpc++/grpc++.h> |
| |
| #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<Monster> *request, |
| flatbuffers::BufferRef<Stat> *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<Stat>(fbb_.GetBufferPointer(), |
| fbb_.GetSize()); |
| return grpc::Status::OK; |
| } |
| virtual ::grpc::Status Retrieve(::grpc::ServerContext *context, |
| const flatbuffers::BufferRef<Stat> *request, |
| flatbuffers::BufferRef<Monster> *response) |
| 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<std::mutex> 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<Monster>(fbb.GetBufferPointer(), |
| fbb.GetSize()); |
| flatbuffers::BufferRef<Stat> 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; |
| } |
| |