mirror of https://github.com/grpc/grpc.git
commit
39bd784e36
5 changed files with 366 additions and 0 deletions
@ -0,0 +1,96 @@ |
||||
#
|
||||
# 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.
|
||||
#
|
||||
HOST_SYSTEM = $(shell uname | cut -f 1 -d_)
|
||||
SYSTEM ?= $(HOST_SYSTEM)
|
||||
CXX = g++
|
||||
CPPFLAGS += `pkg-config --cflags protobuf grpc`
|
||||
CXXFLAGS += -std=c++11
|
||||
ifeq ($(SYSTEM),Darwin) |
||||
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
|
||||
-lgrpc++_reflection\
|
||||
-ldl
|
||||
else |
||||
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
|
||||
-Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed\
|
||||
-ldl
|
||||
endif |
||||
PROTOC = protoc
|
||||
GRPC_CPP_PLUGIN = grpc_cpp_plugin
|
||||
GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)`
|
||||
PROTOS_PATH = ../../protos
|
||||
vpath %.proto $(PROTOS_PATH)
|
||||
all: system-check greeter_client greeter_server
|
||||
greeter_client: helloworld.pb.o helloworld.grpc.pb.o greeter_client.o
|
||||
$(CXX) $^ $(LDFLAGS) -o $@
|
||||
greeter_server: helloworld.pb.o helloworld.grpc.pb.o greeter_server.o
|
||||
$(CXX) $^ $(LDFLAGS) -o $@
|
||||
.PRECIOUS: %.grpc.pb.cc
|
||||
%.grpc.pb.cc: %.proto |
||||
$(PROTOC) -I $(PROTOS_PATH) --grpc_out=. --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN_PATH) $<
|
||||
.PRECIOUS: %.pb.cc
|
||||
%.pb.cc: %.proto |
||||
$(PROTOC) -I $(PROTOS_PATH) --cpp_out=. $<
|
||||
clean:
|
||||
rm -f *.o *.pb.cc *.pb.h greeter_client greeter_server
|
||||
# The following is to test your system and ensure a smoother experience.
|
||||
# They are by no means necessary to actually compile a grpc-enabled software.
|
||||
PROTOC_CMD = which $(PROTOC)
|
||||
PROTOC_CHECK_CMD = $(PROTOC) --version | grep -q libprotoc.3
|
||||
PLUGIN_CHECK_CMD = which $(GRPC_CPP_PLUGIN)
|
||||
HAS_PROTOC = $(shell $(PROTOC_CMD) > /dev/null && echo true || echo false)
|
||||
ifeq ($(HAS_PROTOC),true) |
||||
HAS_VALID_PROTOC = $(shell $(PROTOC_CHECK_CMD) 2> /dev/null && echo true || echo false)
|
||||
endif |
||||
HAS_PLUGIN = $(shell $(PLUGIN_CHECK_CMD) > /dev/null && echo true || echo false)
|
||||
SYSTEM_OK = false
|
||||
ifeq ($(HAS_VALID_PROTOC),true) |
||||
ifeq ($(HAS_PLUGIN),true) |
||||
SYSTEM_OK = true
|
||||
endif |
||||
endif |
||||
system-check:
|
||||
ifneq ($(HAS_VALID_PROTOC),true) |
||||
@echo " DEPENDENCY ERROR"
|
||||
@echo
|
||||
@echo "You don't have protoc 3.0.0 installed in your path."
|
||||
@echo "Please install Google protocol buffers 3.0.0 and its compiler."
|
||||
@echo "You can find it here:"
|
||||
@echo
|
||||
@echo " https://github.com/google/protobuf/releases/tag/v3.0.0"
|
||||
@echo
|
||||
@echo "Here is what I get when trying to evaluate your version of protoc:"
|
||||
@echo
|
||||
-$(PROTOC) --version
|
||||
@echo
|
||||
@echo
|
||||
endif |
||||
ifneq ($(HAS_PLUGIN),true) |
||||
@echo " DEPENDENCY ERROR"
|
||||
@echo
|
||||
@echo "You don't have the grpc c++ protobuf plugin installed in your path."
|
||||
@echo "Please install grpc. You can find it here:"
|
||||
@echo
|
||||
@echo " https://github.com/grpc/grpc"
|
||||
@echo
|
||||
@echo "Here is what I get when trying to detect if you have the plugin:"
|
||||
@echo
|
||||
-which $(GRPC_CPP_PLUGIN)
|
||||
@echo
|
||||
@echo
|
||||
endif |
||||
ifneq ($(SYSTEM_OK),true) |
||||
@false
|
||||
endif |
@ -0,0 +1,66 @@ |
||||
# Metadata Example |
||||
|
||||
## Overview |
||||
|
||||
This example shows you how to add custom headers on the client and server and |
||||
how to access them. |
||||
|
||||
Custom metadata must follow the "Custom-Metadata" format listed in |
||||
https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md, with the |
||||
exception of binary headers, which don't have to be base64 encoded. |
||||
|
||||
### Get the tutorial source code |
||||
The example code for this and our other examples lives in the `examples` directory. Clone this repository to your local machine by running the following command: |
||||
```sh |
||||
$ git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc |
||||
``` |
||||
Change your current directory to examples/cpp/metadata |
||||
```sh |
||||
$ cd examples/cpp/metadata |
||||
``` |
||||
|
||||
### Generating gRPC code |
||||
To generate the client and server side interfaces: |
||||
```sh |
||||
$ make helloworld.grpc.pb.cc helloworld.pb.cc |
||||
``` |
||||
Which internally invokes the proto-compiler as: |
||||
```sh |
||||
$ protoc -I ../../protos/ --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin ../../protos/helloworld.proto |
||||
$ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto |
||||
``` |
||||
### Try it! |
||||
Build client and server: |
||||
|
||||
```sh |
||||
$ make |
||||
``` |
||||
|
||||
Run the server, which will listen on port 50051: |
||||
|
||||
```sh |
||||
$ ./greeter_server |
||||
``` |
||||
|
||||
Run the client (in a different terminal): |
||||
|
||||
```sh |
||||
$ ./greeter_client |
||||
``` |
||||
|
||||
If things go smoothly, you will see in the client terminal: |
||||
|
||||
"Client received initial metadata from server: initial metadata value" |
||||
"Client received trailing metadata from server: trailing metadata value" |
||||
"Client received message: Hello World" |
||||
|
||||
|
||||
And in the server terminal: |
||||
|
||||
"Header key: custom-bin , value: 01234567" |
||||
"Header key: custom-header , value: Custom Value" |
||||
"Header key: user-agent , value: grpc-c++/1.16.0-dev grpc-c/6.0.0-dev (linux; chttp2; gao)" |
||||
|
||||
We did not add the user-agent metadata as a custom header. This shows how |
||||
the gRPC framework adds some headers under the hood that may show up in the |
||||
metadata map. |
@ -0,0 +1,95 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015 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 <iostream> |
||||
#include <memory> |
||||
#include <string> |
||||
|
||||
#include <grpcpp/grpcpp.h> |
||||
|
||||
#ifdef BAZEL_BUILD |
||||
#include "examples/protos/helloworld.grpc.pb.h" |
||||
#else |
||||
#include "helloworld.grpc.pb.h" |
||||
#endif |
||||
|
||||
using grpc::Channel; |
||||
using grpc::ClientContext; |
||||
using grpc::Status; |
||||
using helloworld::HelloRequest; |
||||
using helloworld::HelloReply; |
||||
using helloworld::Greeter; |
||||
|
||||
class CustomHeaderClient { |
||||
public: |
||||
CustomHeaderClient(std::shared_ptr<Channel> channel) |
||||
: stub_(Greeter::NewStub(channel)) {} |
||||
|
||||
// Assembles the client's payload, sends it and presents the response back
|
||||
// from the server.
|
||||
std::string SayHello(const std::string& user) { |
||||
// Data we are sending to the server.
|
||||
HelloRequest request; |
||||
request.set_name(user); |
||||
|
||||
// Container for the data we expect from the server.
|
||||
HelloReply reply; |
||||
|
||||
// Context for the client. It could be used to convey extra information to
|
||||
// the server and/or tweak certain RPC behaviors.
|
||||
ClientContext context; |
||||
|
||||
// Setting custom metadata to be sent to the server
|
||||
context.AddMetadata("custom-header", "Custom Value"); |
||||
|
||||
// Setting custom binary metadata
|
||||
char bytes[8] = {'\0', '\1', '\2', '\3', |
||||
'\4', '\5', '\6', '\7'}; |
||||
context.AddMetadata("custom-bin", grpc::string(bytes, 8)); |
||||
|
||||
// The actual RPC.
|
||||
Status status = stub_->SayHello(&context, request, &reply); |
||||
|
||||
// Act upon its status.
|
||||
if (status.ok()) { |
||||
std::cout << "Client received initial metadata from server: " << context.GetServerInitialMetadata().find("custom-server-metadata")->second << std::endl; |
||||
std::cout << "Client received trailing metadata from server: " << context.GetServerTrailingMetadata().find("custom-trailing-metadata")->second << std::endl; |
||||
return reply.message(); |
||||
} else { |
||||
std::cout << status.error_code() << ": " << status.error_message() |
||||
<< std::endl; |
||||
return "RPC failed"; |
||||
} |
||||
} |
||||
|
||||
private: |
||||
std::unique_ptr<Greeter::Stub> 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()).
|
||||
CustomHeaderClient greeter(grpc::CreateChannel( |
||||
"localhost:50051", grpc::InsecureChannelCredentials())); |
||||
std::string user("world"); |
||||
std::string reply = greeter.SayHello(user); |
||||
std::cout << "Client received message: " << reply << std::endl; |
||||
return 0; |
||||
} |
@ -0,0 +1,94 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015 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 <iostream> |
||||
#include <memory> |
||||
#include <string> |
||||
|
||||
#include <grpcpp/grpcpp.h> |
||||
|
||||
#ifdef BAZEL_BUILD |
||||
#include "examples/protos/helloworld.grpc.pb.h" |
||||
#else |
||||
#include "helloworld.grpc.pb.h" |
||||
#endif |
||||
|
||||
using grpc::Server; |
||||
using grpc::ServerBuilder; |
||||
using grpc::ServerContext; |
||||
using grpc::Status; |
||||
using helloworld::HelloRequest; |
||||
using helloworld::HelloReply; |
||||
using helloworld::Greeter; |
||||
|
||||
// Logic and data behind the server's behavior.
|
||||
class GreeterServiceImpl final : public Greeter::Service { |
||||
Status SayHello(ServerContext* context, const HelloRequest* request, |
||||
HelloReply* reply) override { |
||||
std::string prefix("Hello "); |
||||
|
||||
// Get the client's initial metadata
|
||||
std::cout << "Client metadata: " << std::endl; |
||||
const std::multimap<grpc::string_ref, grpc::string_ref> metadata = context->client_metadata(); |
||||
for (auto iter = metadata.begin(); iter != metadata.end(); ++iter) { |
||||
std::cout << "Header key: " << iter->first << ", value: "; |
||||
// Check for binary value
|
||||
size_t isbin = iter->first.find("-bin"); |
||||
if ((isbin != std::string::npos) && (isbin + 4 == iter->first.size())) { |
||||
std::cout << std::hex; |
||||
for (auto c : iter->second) { |
||||
std::cout << static_cast<unsigned int>(c); |
||||
} |
||||
std::cout << std::dec; |
||||
} else { |
||||
std::cout << iter->second; |
||||
} |
||||
std::cout << std::endl; |
||||
} |
||||
|
||||
context->AddInitialMetadata("custom-server-metadata", "initial metadata value"); |
||||
context->AddTrailingMetadata("custom-trailing-metadata", "trailing metadata value"); |
||||
reply->set_message(prefix + request->name()); |
||||
return Status::OK; |
||||
} |
||||
}; |
||||
|
||||
void RunServer() { |
||||
std::string server_address("0.0.0.0:50051"); |
||||
GreeterServiceImpl 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> 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; |
||||
} |
Loading…
Reference in new issue