125 lines
4.3 KiB
C++
125 lines
4.3 KiB
C++
/*
|
|
* 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,
|
|
::grpc::ServerWriter< flatbuffers::BufferRef<Monster>>* 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<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;
|
|
}
|
|
|