Merge remote-tracking branch 'upstream/master'

pull/3109/head
jayantkolhe 10 years ago
commit c5174ac915
  1. 88
      AUTH.md
  2. 190
      PROTOCOL-HTTP2.md
  3. 514
      README.md
  4. 41
      Step_0.md
  5. 33
      Step_1.md
  6. 85
      Step_2.md
  7. 82
      Step_3.md
  8. 53
      cpp/README.md
  9. 130
      cpp/cpptutorial.md
  10. 110
      cpp/helloworld/Makefile
  11. 95
      cpp/helloworld/README.md
  12. 91
      cpp/helloworld/greeter_client.cc
  13. 84
      cpp/helloworld/greeter_server.cc
  14. 640
      cpp/helloworld/helloworld.pb.cc
  15. 359
      cpp/helloworld/helloworld.pb.h
  16. 49
      go/README.md
  17. 69
      go/greeter_client/main.go
  18. 65
      go/greeter_server/main.go
  19. 109
      go/helloworld/helloworld.pb.go
  20. 0
      java/pom.xml
  21. 4
      java/run_greeter_client.sh
  22. 4
      java/run_greeter_server.sh
  23. 14
      java/src/main/java/ex/grpc/GreeterClient.java
  24. 126
      java/src/main/java/ex/grpc/GreeterGrpc.java
  25. 4
      java/src/main/java/ex/grpc/GreeterImpl.java
  26. 8
      java/src/main/java/ex/grpc/GreeterServer.java
  27. 12
      java/src/main/java/ex/grpc/Helloworld.java
  28. 3
      node/.gitignore
  29. 38
      node/README.md
  30. 52
      node/greeter_client.js
  31. 63
      node/greeter_server.js
  32. 50
      node/helloworld.proto
  33. 10
      node/package.json
  34. 120
      node/route_guide/route_guide.proto
  35. 231
      node/route_guide/route_guide_client.js
  36. 601
      node/route_guide/route_guide_db.json
  37. 249
      node/route_guide/route_guide_server.js
  38. 8
      protos/README.md
  39. 53
      protos/hellostreamingworld.proto
  40. 50
      protos/helloworld.proto
  41. 120
      protos/route_guide.proto
  42. 15
      ruby/.gitignore
  43. 15
      ruby/Gemfile
  44. 35
      ruby/README.md
  45. 23
      ruby/greeter.gemspec
  46. 50
      ruby/greeter_client.rb
  47. 60
      ruby/greeter_server.rb
  48. 18
      ruby/lib/helloworld.rb
  49. 24
      ruby/lib/helloworld_services.rb
  50. 22
      src/main/proto/helloworld.proto

@ -0,0 +1,88 @@
#gRPC Authentication support
gRPC is designed to plug-in a number of authentication mechanisms. We provide an overview
of the various auth mechanisms supported, discuss the API and demonstrate usage through
code examples, and conclude with a discussion of extensibility.
###SSL/TLS
gRPC has SSL/TLS integration and promotes the use of SSL/TLS to authenticate the server,
and encrypt all the data exchanged between the client and the server. Optional
mechanisms are available for clients to provide certificates to accomplish mutual
authentication.
###OAuth 2.0
gRPC provides a generic mechanism (described below) to attach metadata to requests
and responses. This mechanism can be used to attach OAuth 2.0 Access Tokens to
RPCs being made at a client. Additional support for acquiring Access Tokens while
accessing Google APIs through gRPC is provided for certain auth flows, demonstrated
through code examples below.
###API
To reduce complexity and minimize API clutter, gRPC works with a unified concept of
a Credentials object. Users construct gRPC credentials using corresponding bootstrap
credentials (e.g., SSL client certs or Service Account Keys), and use the
credentials while creating a gRPC channel to any server. Depending on the type of
credential supplied, the channel uses the credentials during the initial SSL/TLS
handshake with the server, or uses the credential to generate and attach Access
Tokens to each request being made on the channel.
###Code Examples
####SSL/TLS for server authentication and encryption
This is the simplest authentication scenario, where a client just wants to
authenticate the server and encrypt all data.
```
SslCredentialsOptions ssl_opts; // Options to override SSL params, empty by default
// Create the credentials object by providing service account key in constructor
std::unique_ptr<Credentials> creds = CredentialsFactory::SslCredentials(ssl_opts);
// Create a channel using the credentials created in the previous step
std::shared_ptr<ChannelInterface> channel = CreateChannel(server_name, creds, channel_args);
// Create a stub on the channel
std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
// Make actual RPC calls on the stub.
grpc::Status s = stub->sayHello(&context, *request, response);
```
For advanced use cases such as modifying the root CA or using client certs,
the corresponding options can be set in the SslCredentialsOptions parameter
passed to the factory method.
###Authenticating with Google
gRPC applications can use a simple API to create a credential that works in various deployment scenarios.
```
std::unique_ptr<Credentials> creds = CredentialsFactory::DefaultGoogleCredentials();
// Create a channel, stub and make RPC calls (same as in the previous example)
std::shared_ptr<ChannelInterface> channel = CreateChannel(server_name, creds, channel_args);
std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
grpc::Status s = stub->sayHello(&context, *request, response);
```
This credential works for applications using Service Accounts as well as for
applications running in Google Compute Engine (GCE). In the former case, the
service account’s private keys are expected in file located at [TODO: well
known file fath for service account keys] or in the file named in the environment
variable [TODO: add the env var name here]. The keys are used at run-time to
generate bearer tokens that are attached to each outgoing RPC on the
corresponding channel.
For applications running in GCE, a default service account and corresponding
OAuth scopes can be configured during VM setup. At run-time, this credential
handles communication with the authentication systems to obtain OAuth2 access
tokens and attaches them to each outgoing RPC on the corresponding channel.
Extending gRPC to support other authentication mechanisms
The gRPC protocol is designed with a general mechanism for sending metadata
associated with RPC. Clients can send metadata at the beginning of an RPC and
servers can send back metadata at the beginning and end of the RPC. This
provides a natural mechanism to support OAuth2 and other authentication
mechanisms that need attach bearer tokens to individual request.
In the simplest case, there is a single line of code required on the client
to add a specific token as metadata to an RPC and a corresponding access on
the server to retrieve this piece of metadata. The generation of the token
on the client side and its verification at the server can be done separately.
A deeper integration can be achieved by plugging in a gRPC credentials implementation for any custom authentication mechanism that needs to attach per-request tokens. gRPC internals also allow switching out SSL/TLS with other encryption mechanisms.

@ -0,0 +1,190 @@
# gRPC over HTTP2
## Introduction
This document serves as a detailed description for an implementation of gRPC carried over HTTP2 draft 17 framing. It assumes familiarity with the HTTP2 specification.
## Protocol
Production rules are using <a href="http://tools.ietf.org/html/rfc5234">ABNF syntax</a>.
### Outline
The following is the general sequence of message atoms in a GRPC request & response message stream
* Request → Request-Headers *Delimited-Message EOS
* Response → (Response-Headers *Delimited-Message Trailers) / Trailers-Only
### Requests
* Request → Request-Headers *Delimited-Message EOS
Request-Headers are delivered as HTTP2 headers in HEADERS + CONTINUATION frames.
* **Request-Headers** → Call-Definition *Custom-Metadata
* **Call-Definition** → Method Scheme Path TE [Authority] [Timeout] [Content-Type] [Message-Type] [Message-Encoding] [User-Agent]
* **Method** → “:method POST”
* **Scheme** → “:scheme ” (“http” / “https”)
* **Path** → “:path” {_path identifying method within exposed API_}
* **Authority** → “:authority” {_virtual host name of authority_}
* **TE** → “te” “trailers” # Used to detect incompatible proxies
* **Timeout** → “grpc-timeout” TimeoutValue TimeoutUnit
* **TimeoutValue** → {_positive integer as ASCII string of at most 8 digits_}
* **TimeoutUnit** → Hour / Minute / Second / Millisecond / Microsecond / Nanosecond
* **Hour** → “H”
* **Minute** → “M”
* **Second** → “S”
* **Millisecond** → “m”
* **Microsecond** → “u”
* **Nanosecond** → “n”
* **Content-Type** → “content-type” “application/grpc” [(“+proto” / “+json” / {_custom_})]
* **Message-Encoding** → “grpc-encoding ” (“gzip” / “deflate” / “snappy” / {_custom_} )
* **User-Agent** → “user-agent” {_structured user-agent string_}
* **Message-Type** → “grpc-message-type” {_type name for message schema_}
* **Custom-Metadata** → Binary-Header / ASCII-Header
* **Binary-Header** → {lowercase ASCII header name ending in “-bin” } {_base64 encoded value_}
* **ASCII-Header** → {lowercase ASCII header name} {_value_}
HTTP2 requires that reserved headers, ones starting with “:” appear before all other headers. Additionally implementations should send **Timeout** immediately after the reserved headers and they should send the **Call-Definition** headers before sending **Custom-Metadata**.
If **Timeout** is omitted a server should assume an infinite timeout. Client implementations are free to send a default minimum timeout based on their deployment requirements.
**Custom-Metadata** is an arbitrary set of key-value pairs defined by the application layer. Aside from transport limits on the total length of HTTP2 HEADERS the only other constraint is that header names starting with “grpc-” are reserved for future use.
Note that HTTP2 does not allow arbitrary octet sequences for header values so binary header values must be encoded using Base64 as per https://tools.ietf.org/html/rfc4648#section-4. Implementations MUST accept padded and un-padded values and should emit un-padded values. Applications define binary headers by having their names end with “-bin”. Runtime libraries use this suffix to detect binary headers and properly apply base64 encoding & decoding as headers are sent and received.
The repeated sequence of **Delimited-Message** items is delivered in DATA frames
* **Delimited-Message** → Compressed-Flag Message-Length Message
* **Compressed-Flag** → 0 / 1 # encoded as 1 byte unsigned integer
* **Message-Length** → {_length of Message_} # encoded as 4 byte unsigned integer
* **Message** → *{binary octet}
A **Compressed-Flag** value of 1 indicates that the binary octet sequence of **Message** is compressed using the mechanism declared by the **Message-Encoding** header. A value of 0 indicates that no encoding of **Message** bytes has occurred. Compression contexts are NOT maintained over message boundaries, implementations must create a new context for each message in the stream. If the **Message-Encoding** header is omitted then the **Compressed-Flag** must be 0.
For requests, **EOS** (end-of-stream) is indicated by the presence of the END_STREAM flag on the last received DATA frame. In scenarios where the **Request** stream needs to be closed but no data remains to be sent implementations MUST send an empty DATA frame with this flag set.
###Responses
* **Response** → (Response-Headers *Delimited-Message Trailers) / Trailers-Only
* **Response-Headers** → HTTP-Status [Message-Encoding] Content-Type *Custom-Metadata
* **Trailers-Only** → HTTP-Status Content-Type Trailers
* **Trailers** → Status [Status-Message] *Custom-Metadata
* **HTTP-Status** → “:status 200”
* **Status** → “grpc-status” <status-code-as-ASCII-string>
* **Status-Message** → “grpc-message” <descriptive text for status as ASCII string>
**Response-Headers** & **Trailers-Only** are each delivered in a single HTTP2 HEADERS frame block. Most responses are expected to have both headers and trailers but **Trailers-Only** is permitted for calls that produce an immediate error. Status must be sent in **Trailers** even if the status code is OK.
For responses end-of-stream is indicated by the presence of the END_STREAM flag on the last received HEADERS frame that carries **Trailers**.
Implementations should expect broken deployments to send non-200 HTTP status codes in responses as well as a variety of non-GRPC content-types and to omit **Status** & **Status-Message**. Implementations must synthesize a **Status** & **Status-Message** to propagate to the application layer when this occurs.
####Example
Sample unary-call showing HTTP2 framing sequence
**Request**
```
HEADERS (flags = END_HEADERS)
:method = POST
:scheme = http
:path = /google.pubsub.v2.PublisherService/CreateTopic
:authority = pubsub.googleapis.com
grpc-timeout = 1S
content-type = application/grpc+proto
grpc-encoding = gzip
authorization = Bearer y235.wef315yfh138vh31hv93hv8h3v
DATA (flags = END_STREAM)
<Delimited Message>
```
**Response**
```
HEADERS (flags = END_HEADERS)
:status = 200
grpc-encoding = gzip
DATA
<Delimited Message>
HEADERS (flags = END_STREAM, END_HEADERS)
grpc-status = 0 # OK
trace-proto-bin = jher831yy13JHy3hc
```
####User Agents
While the protocol does not require a user-agent to function it is recommended that clients provide a structured user-agent string that provides a basic description of the calling library, version & platform to facilitate issue diagnosis in heterogeneous environments. The following structure is recommended to library developers
```
User-Agent → “grpc-” Language ?(“-” Variant) “/” Version ?( “ (“ *(AdditionalProperty “;”) “)” )
```
E.g.
```
grpc-java/1.2.3
grpc-ruby/1.2.3
grpc-ruby-jruby/1.3.4
grpc-java-android/0.9.1 (gingerbread/1.2.4; nexus5; tmobile)
```
####HTTP2 Transport Mapping
#####Stream Identification
All GRPC calls need to specify an internal ID. We will use HTTP2 stream-ids as call identifiers in this scheme. NOTE: These id’s are contextual to an open HTTP2 session and will not be unique within a given process that is handling more than one HTTP2 session nor can they be used as GUIDs.
#####Data Frames
DATA frame boundaries have no relation to **Delimited-Message** boundaries and implementations should make no assumptions about their alignment.
#####Errors
When an application or runtime error occurs during an RPC a **Status** and **Status-Message** are delivered in **Trailers**.
In some cases it is possible that the framing of the message stream has become corrupt and the RPC runtime will choose to use an **RST_STREAM** frame to indicate this state to its peer. RPC runtime implementations should interpret RST_STREAM as immediate full-closure of the stream and should propagate an error up to the calling application layer.
The following mapping from RST_STREAM error codes to GRPC error codes is applied.
HTTP2 Code|GRPC Code
----------|-----------
NO_ERROR(0)|INTERNAL - An explicit GRPC status of OK should have been sent but this might be used to aggressively lameduck in some scenarios.
PROTOCOL_ERROR(1)|INTERNAL
INTERNAL_ERROR(2)|INTERNAL
FLOW_CONTROL_ERROR(3)|INTERNAL
SETTINGS_TIMEOUT(4)|INTERNAL
STREAM_CLOSED|No mapping as there is no open stream to propagate to. Implementations should log.
FRAME_SIZE_ERROR|INTERNAL
REFUSED_STREAM|UNAVAILABLE - Indicates that no processing occurred and the request can be retried, possibly elsewhere.
CANCEL(8)|Mapped to call cancellation when sent by a client.Mapped to CANCELLED when sent by a server. Note that servers should only use this mechanism when they need to cancel a call but the payload byte sequence is incomplete.
COMPRESSION_ERROR|INTERNAL
CONNECT_ERROR|INTERNAL
ENHANCE_YOUR_CALM|RESOURCE_EXHAUSTED ...with additional error detail provided by runtime to indicate that the exhausted resource is bandwidth.
INADEQUATE_SECURITY| PERMISSION_DENIED … with additional detail indicating that permission was denied as protocol is not secure enough for call.
#####Security
The HTTP2 specification mandates the use of TLS 1.2 or higher when TLS is used with HTTP2. It also places some additional constraints on the allowed ciphers in deployments to avoid known-problems as well as requiring SNI support. It is also expected that HTTP2 will be used in conjunction with proprietary transport security mechanisms about which the specification can make no meaningful recommendations.
#####Connection Management
######GOAWAY Frame
Sent by servers to clients to indicate that they will no longer accept any new streams on the associated connections. This frame includes the id of the last successfully accepted stream by the server. Clients should consider any stream initiated after the last successfully accepted stream as UNAVAILABLE and retry the call elsewhere. Clients are free to continue working with the already accepted streams until they complete or the connection is terminated.
Servers should send GOAWAY before terminating a connection to reliably inform clients which work has been accepted by the server and is being executed.
######PING Frame
Both clients and servers can send a PING frame that the peer must respond to by precisely echoing what they received. This is used to assert that the connection is still live as well as providing a means to estimate end-to-end latency. If a server initiated PING does not receive a response within the deadline expected by the runtime all outstanding calls on the server will be closed with a CANCELLED status. An expired client initiated PING will cause all calls to be closed with an UNAVAILABLE status. Note that the frequency of PINGs is highly dependent on the network environment, implementations are free to adjust PING frequency based on network and application requirements.
######Connection failure
If a detectable connection failure occurs on the client all calls will be closed with an UNAVAILABLE status. For servers open calls will be closed with a CANCELLED status.
### Appendix A - GRPC for Protobuf
The service interfaces declared by protobuf are easily mapped onto GRPC by code generation extensions to protoc. The following defines the mapping to be used
* **Path** → / Service-Name / {_method name_}
* **Service-Name** → ?( {_proto package name_} "." ) {_service name_}
* **Message-Type** → {_fully qualified proto message name_}
* **Content-Type** → "application/grpc+proto"

@ -1,81 +1,511 @@
# gRPC Helloworld Tutorial
## TODO: move this to the tutorial sub-folder # Getting started
A great way to get introduced to gRPC is to work through this tutorial, which Welcome to the developer documentation for gRPC, a language-neutral,
walks you through the construction of simple client and server that introduces platform-neutral remote procedure call (RPC) system developed at Google.
various features of gRPC.
When you finish the tutorial, you will be able to This document introduces you to gRPC with a quick overview and a simple
Hello World example. More documentation is coming soon!
- Create an protobuf schema that defines a simple RPC service ## Quick start
- Create a Java server that implements the schema interface You can find quick start guides for each language, including installation instructions and examples here:
- Create a Java client that accesses the server * [C++](https://github.com/grpc/grpc-common/tree/master/cpp)
- Create a Go client that accesses the Java server * [Java](https://github.com/grpc/grpc-common/tree/master/java)
- Update the service with advanced features like RPC streaming * [Python](https://github.com/grpc/grpc-common/tree/master/python)
* [Go](https://github.com/grpc/grpc-common/tree/master/go)
* [ruby](https://github.com/grpc/grpc-common/tree/master/ruby)
* [Node.js](https://github.com/grpc/grpc-common/tree/master/node)
# Get Started ## What's in this repository?
The rest of this page explains how you can set up your local machine for development. The `grpc-common` repository contains documentation, resources, and examples
If you just want to read the tutorial, you can go straight to the next step: [Step - 0](Step_0.md) for all gRPC users. You can find examples and instructions specific to your
favourite language in the relevant subdirectory.
# Working with the code You can find out about the gRPC source code repositories in
[`grpc`](https://github.com/grpc/grpc). Each repository provides instructions
for building the appropriate libraries for your language.
You can follow along with this tutorial and hack on the code in the comfort of
your own computer. In this way you can get hands-on practice of really writing
gRPC code.
The tutorial relies on the use of the Git versioning system for source code ## What is gRPC?
management. You don't need to know anything about Git to follow the tutorial
other than how to install and run a few git commands.
# Install Git In gRPC a *client* application can directly call
methods on a *server* application on a different machine as if it was a
local object, making it easier for you to create distributed applications and
services. As in many RPC systems, gRPC is based around the idea of defining
a *service*, specifying the methods that can be called remotely with their
parameters and return types. On the server side, the server implements this
interface and runs a gRPC server to handle client calls. On the client side,
the client has a *stub* that provides exactly the same methods as the server.
##TODO: diagram?
gRPC clients and servers can run and talk to each other in a variety of
environments - from servers inside Google to your own desktop - and can
be written in any of gRPC's [supported languages](link to list). So, for
example, you can easily create a gRPC server in Java with clients in Go,
Python, or Ruby. In addition, the latest Google APIs will have gRPC versions
of their interfaces, letting you easily build Google functionality into
your applications.
<a name="protocolbuffers"></a>
### Working with protocol buffers
By default gRPC uses *protocol buffers*, Google’s
mature open source mechanism for serializing structured data (although it
can be used with other data formats such as JSON). As you'll
see in our example below, you define gRPC services using *proto files*,
with method parameters and return types specified as protocol buffer message
types. You
can find out lots more about protocol buffers in the [Protocol Buffers
documentation](https://developers.google.com/protocol-buffers/docs/overview).
#### Protocol buffer versions
While protocol buffers have been available for open source users for some
time, our examples use a new flavour of protocol buffers called proto3,
which has a slightly simplified syntax, some useful new features, and supports
lots more languages. This is currently available as an alpha release in
Java, C++, Java_nano (Android Java), Python, and Ruby from [the protocol buffers Github
repo](https://github.com/google/protobuf/releases), as well as a Go language
generator from [the golang/protobuf Github repo](https://github.com/golang/protobuf), with more languages in development. Full documentation for proto3 is currently in development, but you can see
the major differences from the current default version in the [release notes](https://github.com/google/protobuf/releases).
In general, while you *can* use proto2 (the current default protocol buffers version), we recommend that you use proto3 with gRPC as it lets you use the full range of gRPC-supported languages, as well as avoiding compatibility
issues with proto2 clients talking to proto3 servers and vice versa.
<a name="hello"></a>
## Hello gRPC!
Now that you know a bit more about gRPC, the easiest way to see how it
works is to look at a simple example. Our Hello World walks you through the
construction of a simple gRPC client-server application, showing you how to:
- Create a protocol buffers schema that defines a simple RPC service with
a single
Hello World method.
- Create a Java server that implements this interface.
- Create a Java client that accesses the Java server.
- Create a Go client that accesses
the same Java server.
- Update the service with a streaming RPC.
The complete code for the example is available in the `grpc-common` GitHub
repository. We use the Git versioning system for source code management:
however, you don't need to know anything about Git to follow along other
than how to install and run a few git commands.
This is an introductory example rather than a comprehensive tutorial, so
don't worry if you're not a Go or
Java developer - the concepts are similar for all languages, and you can
find more implementations of our Hello World example in other languages in
the language-specific folders in this repository. Complete tutorials and
reference documentation for all gRPC languages are coming soon.
<a name="setup"></a>
### Setup
This section explains how to set up your local machine to work with
the example code. If you just want to read the example, you can go straight
to the [next step](#servicedef).
#### Install Git
You can download and install Git from http://git-scm.com/download. Once You can download and install Git from http://git-scm.com/download. Once
installed you should have access to the git command line tool. The main installed you should have access to the git command line tool. The main
commands that you will need to use are: commands that you will need to use are:
- git clone ... : clone a remote repository onto your local machine - git clone ... : clone a remote repository onto your local machine
- git checkout ... : check out a particular branch or a tagged version of the code to hack on - git checkout ... : check out a particular branch or a tagged version of
the code to hack on
# Download grpc-helloworld #### Get the source code
The example code for this and our other examples lives in the `grpc-common`
GitHub repository. Clone this repository to your local machine by running the
following command:
Clone the grpc-helloword repository located at GitHub by running the following command:
``` ```
git clone https://github.com/google/grpc-helloworld.git git clone https://github.com/google/grpc-common.git
``` ```
Change your current directory to grpc-helloworld Change your current directory to grpc-common/java
``` ```
cd grpc-helloworld cd grpc-common/java
``` ```
# Install Java 8 #### Install Java 8
Java gRPC is designed to work with both Java 7 and Java 8. For simplicity, Java gRPC is designed to work with both Java 7 and Java 8 - our example uses
the example assumes that Java 8 is installed. See Java 8. See
[Install Java 8](http://docs.oracle.com/javase/8/docs/technotes/guides/install/install_overview.html) [Install Java
for instructions. 8](http://docs.oracle.com/javase/8/docs/technotes/guides/install/install_overview.html)
for instructions if you need to install Java 8.
# Install Maven #### Install Maven
To simplify building and the managing of gRPC's dependencies, the java client To simplify building and managing gRPC's dependencies, the Java client
are server are structured as a standard [Maven](http://maven.apache.org/guides/getting-started/) and server are structured as a standard
project. See [Install Maven](http://maven.apache.org/users/index.html) for instructions. [Maven](http://maven.apache.org/guides/getting-started/)
project. See [Install Maven](http://maven.apache.org/users/index.html)
for instructions.
# Install Go 1.4 #### Install Go 1.4
Go gRPC requires Go 1.4, the latest version of Go. See Go gRPC requires Go 1.4, the latest version of Go. See
[Install Go](https://golang.org/doc/install) for instructions. [Install Go](https://golang.org/doc/install) for instructions.
# (optional) Install protoc #### (optional) Install protoc
gRPC uses the latest version of the protocol buffer compiler, protoc. gRPC uses the latest version of the [protocol
buffer](https://developers.google.com/protocol-buffers/docs/overview)
compiler, protoc.
For following this tutorial, the protoc is not strictly necessary, as all the Having protoc installed isn't strictly necessary to follow along with this
generated code is checked into the Git repository. If you want to experiment example, as all the
generated code is checked into the Git repository. However, if you want
to experiment
with generating the code yourself, download and install protoc from its with generating the code yourself, download and install protoc from its
[Git repo](https://github.com/google/protobuf) [Git repo](https://github.com/google/protobuf)
<a name="servicedef"></a>
### Defining a service
The first step in creating our example is to define a *service*: an RPC
service specifies the methods that can be called remotely with their parameters
and return types. As you saw in the
[overview](#protocolbuffers) above, gRPC does this using [protocol
buffers](https://developers.google.com/protocol-buffers/docs/overview). We
use the protocol buffers interface definition language (IDL) to define our
service methods, and define the parameters and return
types as protocol buffer message types. Both the client and the
server use interface code generated from the service definition.
Here's our example service definition, defined using protocol buffers IDL in
[helloworld.proto](protos/helloworld.proto). The `Greeting`
service has one method, `hello`, that lets the server receive a single
`HelloRequest`
message from the remote client containing the user's name, then send back
a greeting in a single `HelloReply`. This is the simplest type of RPC you
can specify in gRPC - we'll look at some other types later in this document.
```
syntax = "proto3";
option java_package = "ex.grpc";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
```
<a name="generating"></a>
### Generating gRPC code
Once we've defined our service, we use the protocol buffer compiler
`protoc` to generate the special client and server code we need to create
our application - right now we're going to generate Java code, though you
can generate gRPC code in any gRPC-supported language (as you'll see later
in this example). The generated code contains both stub code for clients to
use and an abstract interface for servers to implement, both with the method
defined in our `Greeting` service.
(If you didn't install `protoc` on your system and are working along with
the example, you can skip this step and move
onto the next one where we examine the generated code.)
As this is our first time using gRPC, we need to build the protobuf plugin
that generates our RPC
classes. By default `protoc` just generates code for reading and writing
protocol buffers, so you need to use plugins to add additional features
to generated code. As we're creating Java code, we use the gRPC Java plugin.
To build the plugin, follow the instructions in the relevant repo: for Java,
the instructions are in [`grpc-java`](https://github.com/grpc/grpc-java).
To use it to generate the code:
```sh
$ mkdir -p src/main/java
$ protoc -I . helloworld.proto
--plugin=protoc-gen-grpc=external/grpc_java/bins/opt/java_plugin \
--grpc_out=src/main/java \
--java_out=src/main/java
```
[need to update this once I get the plugin built]
This generates the following classes, which contain all the generated code
we need to create our example:
- [`Helloworld.java`](java/src/main/java/ex/grpc/Helloworld.java), which
has all the protocol buffer code to populate, serialize, and retrieve our
`HelloRequest` and `HelloReply` message types
- [`GreeterGrpc.java`](java/src/main/java/ex/grpc/GreeterGrpc.java),
which contains (along with some other useful code):
- an interface for `Greeter` servers to implement
```java
public static interface Greeter {
public void SayHello(ex.grpc.Helloworld.HelloRequest request,
com.google.net.stubby.stub.StreamObserver<ex.grpc.Helloworld.HelloReply>
responseObserver);
}
```
- _stub_ classes that clients can use to talk to a `Greeter` server. As you can see, they also implement the `Greeter` interface.
```java
public static class GreeterStub extends
com.google.net.stubby.stub.AbstractStub<GreeterStub,
GreeterServiceDescriptor>
implements Greeter {
...
}
```
<a name="server"></a>
### Writing a server
Now let's write some code! First we'll create a server application to implement
our service. Note that we're not going to go into a lot of detail about how
to create a server in this section. More detailed information will be in the
tutorial for your chosen language (coming soon).
Our server application has two classes:
- a simple service implementation
[GreeterImpl.java](java/src/main/java/ex/grpc/GreeterImpl.java).
- a server that hosts the service implementation and allows access over the
network: [GreeterServer.java](java/src/main/java/ex/grpc/GreeterServer.java).
#### Service implementation
[GreeterImpl.java](java/src/main/java/ex/grpc/GreeterImpl.java)
actually implements our GreetingService's required behaviour.
As you can see, the class `GreeterImpl` implements the interface
`GreeterGrpc.Greeter` that we [generated](#generating) from our proto
[IDL](java/src/main/proto/helloworld.proto) by implementing the method `hello`:
```java
public void hello(Helloworld.HelloRequest req,
StreamObserver<Helloworld.HelloReply> responseObserver) {
Helloworld.HelloReply reply =
Helloworld.HelloReply.newBuilder().setMessage(
"Hello " + req.getName()).build();
responseObserver.onValue(reply);
responseObserver.onCompleted();
}
```
- `hello` takes two parameters:
-`Helloworld.HelloRequest`: the request
-`StreamObserver<Helloworld.HelloReply>`: a response observer, which is
a special interface for the server to call with its response
To return our response to the client and complete the call:
1. We construct and populate a `HelloReply` response object with our exciting
message, as specified in our interface definition.
2. We use the`responseObserver` to return the `HelloReply` to the client
and then specify that we've finished dealing with the RPC
#### Server implementation
[GreeterServer.java](java/src/main/java/ex/grpc/GreeterServer.java)
shows the other main feature required to provide a gRPC service; making the service
implementation available from the network.
```java
private ServerImpl server;
...
private void start() throws Exception {
server = NettyServerBuilder.forPort(port)
.addService(GreeterGrpc.bindService(new GreeterImpl()))
.build();
server.startAsync();
server.awaitRunning(5, TimeUnit.SECONDS);
}
```
Here we create an appropriate gRPC server, binding the `GreeterService`
implementation that we created to a port. Then we start the server running: the server is now ready to receive
requests from `Greeter` service clients on our specified port. We'll cover
how all this works in a bit more detail in our language-specific documentation.
#### Build it
Once we've implemented everything, we use Maven to build the server:
```
$ mvn package
```
We'll look at using a client to access the server in the next section.
<a name="client"></a>
### Writing a client
Client-side gRPC is pretty simple. In this step, we'll use the generated code
to write a simple client that can access the `Greeter` server we created
in the [previous section](#server). You can see the complete client code in
[GreeterClient.java](java/src/main/java/ex/grpc/GreeterClient.java).
Again, we're not going to go into much detail about how to implement a client;
we'll leave that for the tutorial.
#### Connecting to the service
First let's look at how we connect to the `Greetings` server. First we need
to create a gRPC channel, specifying the hostname and port of the server we
want to connect to. Then we use the channel to construct the stub instance.
```java
private final ChannelImpl channel;
private final GreeterGrpc.GreeterBlockingStub blockingStub;
public HelloClient(String host, int port) {
channel = NettyChannelBuilder.forAddress(host, port)
.negotiationType(NegotiationType.PLAINTEXT)
.build();
blockingStub = GreeterGrpc.newBlockingStub(channel);
}
```
In this case, we create a blocking stub. This means that the RPC call waits
for the server to respond, and will either return a response or raise an
exception. gRPC Java has other kinds of stubs that make non-blocking calls
to the server, where the response is returned asynchronously.
#### Calling an RPC
Now we can contact the service and obtain a greeting:
1. We construct and fill in a `HelloRequest` to send to the service.
2. We call the stub's `hello()` RPC with our request and get a `HelloReply`
back,
from which we can get our greeting.
```java
public void greet(String name) {
logger.debug("Will try to greet " + name + " ...");
try {
Helloworld.HelloRequest request =
Helloworld.HelloRequest.newBuilder().setName(name).build();
Helloworld.HelloReply reply = blockingStub.SayHello(request);
logger.info("Greeting: " + reply.getMessage());
} catch (RuntimeException e) {
logger.log(Level.WARNING, "RPC failed", e);
return;
}
}
```
#### Build the client
This is the same as building the server: our client and server are part of
the same maven package so the same command builds both.
```
$ mvn package
```
<a name="run"></a>
### Try it out!
We've added simple shell scripts to simplifying running the examples. Now
that they are built, you can run the server with:
```sh
$ ./run_greeter_server.sh
```
and in another terminal window confirm that it receives a message.
```sh
$ ./run_greeter_client.sh
```
### Adding another client
Finally, let's look at one of gRPC's most useful features - interoperability
between code in different languages. So far, we've just looked at Java code
generated from and implementing our `Greeter` service definition. However,
as you'll see if you look at the language-specific subdirectories
in this repository, we've also generated and implemented `Greeter`
in some of gRPC's other supported languages. Each service
and client uses interface code generated from [exactly the same
.proto](https://github.com/grpc/grpc-common/blob/master/protos/helloworld.proto)
that we used for the Java example.
So, for example, if we visit the [`go`
directory](https://github.com/grpc/grpc-common/tree/master/go) and look at the
[`greeter_client`](https://github.com/grpc/grpc-common/blob/master/go/greeter_client/main.go),
we can see that like the Java client, it connects to a `Greeter` service
at `localhost:50051` and uses a stub to call the `SayHello` method with a
`HelloRequest`:
```go
const (
address = "localhost:50051"
defaultName = "world"
)
func main() {
// Set up a connection to the server.
conn, err := grpc.Dial(address)
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
// Contact the server and print out its response.
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name:
name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.Message)
}
```
If we run the Java server from earlier in another terminal window, we can
run the Go client and connect to it just like the Java client, even though
it's written in a different language.
```
$ greeter_client
```

@ -1,41 +0,0 @@
# Step-0: define a service
This section presents an example of a simple service definition that receives
a message from a remote client. The message contains the users's name and
sends back a greeting to that person.
It's shown below in full; it's actually contained in separate file
[helloworld.proto](helloworld.proto).
```
syntax = "proto3";
package helloworld;
// The request message containing the user's name.
message HelloRequest {
optional string name = 1;
}
// The response message containing the greetings
message HelloReply {
optional string message = 1;
}
// The greeting service definition.
service Greeting {
// Sends a greeting
rpc hello (HelloRequest) returns (HelloReply) {
}
}
```
The service stanza of the message is an example of protobuf service IDL
(Interface Defintion Language). Here, it defines a simple service that
receives a request containing a name and returns a response containing a
message.
Next, in [Step - 1](Step_1.md), we'll use protoc to generate client code from
this IDL.

@ -1,33 +0,0 @@
# Step-1: Generate a service client.
In this step, we use protoc to generate the java Stub classes. A Stub is the
name gRPC uses for the code that initiates contact with a gRPC service running
remotely via the internet.
If you did not install protoc on your system, you can skip this step and move
onto the next one where we examine the generated code.
First, you'll need to build the protobuf plugin that generates the rpc
classes. `protoc` uses other tools called plugins to add additional features
to generated code.
The grpc Java Stub classes are created using a grpc java plugin, but first the
plugin must be built and installed.
To build the plugin:
```
$ pushd external/grpc_java
$ make java_plugin
$ popd
```
To use it to generate the code:
```
$ mkdir -p src/main/java
$ protoc -I . helloworld.proto --plugin=protoc-gen-grpc=external/grpc_java/bins/opt/java_plugin \
--grpc_out=src/main/java \
--java_out=src/main/java
```
Next, in [Step-2](Step-2.md), we'll use the generated Stub implementation to
write a client that uses the generated code to make a call to a service.

@ -1,85 +0,0 @@
# Step-2: Write a service client.
This step uses the generated code to write a simple client to access the hello
service. The full client is in [GreetingsClient.java](src/main/java/ex/grpc/GreetingsClient.java).
## Configuring the service to connect to.
The client contains uses a Stub to contact the service. The internet address
is configured in the client constructor. gRPC Channel is the abstraction over
transport handling; its constructor accepts the host name and port of the
service. The channel in turn is used to construct the Stub.
```
private final ChannelImpl channel;
private final GreetingGrpc.GreetingBlockingStub blockingStub;
public HelloClient(String host, int port) {
channel = NettyChannelBuilder.forAddress(host, port)
.negotiationType(NegotiationType.PLAINTEXT)
.build();
blockingStub = GreetingGrpc.newBlockingStub(channel);
}
```
## Obtaining a greeting
The greet method uses the stub to contact the service and obtain a greeting.
It:
- constructs a request
- obtains a reply from the stub
- prints out the greeting
```
public void greet(String name) {
logger.debug("Will try to greet " + name + " ...");
try {
Helloworld.HelloRequest request = Helloworld.HelloRequest.newBuilder().setName(name).build();
Helloworld.HelloReply reply = blockingStub.hello(request);
logger.info("Greeting: " + reply.getMessage());
} catch (RuntimeException e) {
logger.log(Level.WARNING, "RPC failed", e);
return;
}
}
```
## Running from the command line
The main method puts together the example so that it can be run from a command
line.
```
/* Access a service running on the local machine on port 50051 */
HelloClient client = new HelloClient("localhost", 50051);
String user = "world";
if (args.length > 1) {
user = args[1];
}
client.greet(user);
```
It can be built as follows.
```
$ mvn package
```
It can also be run, but doing so now would end up a with a failure as there is
no server available yet. The [next step](Step-3.md), describes how to
implement, build and run a server that supports the service description.
## Notes
- the client uses a blocking stub. This means that the RPC call waits for the
server to respond, and will either return a response or raise an exception.
- gRPC Java has other kinds of stubs that make non-blocking calls to the
server, where the response is returned asynchronously. Usage of these stubs
is a more advanced topic and will be described in later steps.

@ -1,82 +0,0 @@
# Step-3: Implement a server.
This step extends the generated server skeleton code to write a simple server
that provides the hello service. This in introduces two new classes
- a service implementation [GreetingsImpl.java](src/main/java/ex/grpc/GreetingsImpl.java).
- a server that hosts the service implementation and allows to accessed over the network: [GreetingsServer.java](src/main/java/ex/grpc/GreetingsServer.java).
## Service implementation
[GreetingsSImpl.java](src/main/java/ex/grpc/GreetingsImpl.java)
implements the behaviour we require of our GreetingService. There are a
number of important features of gRPC being used here:
```
public void hello(Helloworld.HelloRequest req,
StreamObserver<Helloworld.HelloReply> responseObserver) {
Helloworld.HelloReply reply = Helloworld.HelloReply.newBuilder().setMessage(
"Hello " + req.getName()).build();
responseObserver.onValue(reply);
responseObserver.onCompleted();
}
```
- it provides a class `GreetingsImpl` that implements a generated interface `GreetingsGrpc.Greetings`
- `GreetingsGrpc.Greetings` declares the method `hello` that was declared in the proto [IDL](src/main/proto/helloworld.proto)
- `hello's` signature is typesafe:
hello(Helloworld.HelloRequest req, StreamObserver<Helloworld.HelloReply> responseObserver)
- `hello` takes two parameters:
`Helloworld.HelloRequest`: the request
`StreamObserver<Helloworld.HelloReply>`: a response observer, an interface to be called with the response value
- to complete the call
- the return value is constructed
- the responseObserver.onValue() is called with the response
- responseObserver.onCompleted() is called to indicate that no more work will done on the RPC.
## Server implementation
[GreetingsServer.java](src/main/java/ex/grpc/GreetingsServer.java) shows the
other main feature to required to provde gRPC service; how to allow a service
implementation to be accessed from the network.
```
private void start() throws Exception {
server = NettyServerBuilder.forPort(port)
.addService(GreetingsGrpc.bindService(new GreetingsImpl()))
.build();
server.startAsync();
server.awaitRunning(5, TimeUnit.SECONDS);
}
```
- it provides a class `GreetingsServer` that holds a `ServerImpl` that will run the server
- in the `start` method, `GreetingServer` binds the `GreetingsService` implementation to a port and begins running it
- there is also a `stop` method that takes care of shutting down the service and cleaning up when the program exits
## Build it
This is the same as before: our client and server are part of the same maven
package so the same command builds both.
```
$ mvn package
```
## Try them out
We've added simple shell scripts to simplifying running the examples. Now
that they are built, you can run the server with.
```
$ ./run_greetings_server.sh
```
In another termainal window and confirm that it receives a message.
```
$ ./run_greetings_client.sh
```

@ -0,0 +1,53 @@
#gRPC in 3 minutes (C++)
## Installation
To install gRPC on your system, follow the instructions here:
[https://github.com/grpc/grpc/blob/master/INSTALL](https://github.com/grpc/grpc/blob/master/INSTALL).
## Hello C++ gRPC!
Here's how to build and run the C++ implementation of the [Hello World](https://github.com/grpc/grpc-common/blob/master/protos/helloworld.proto) example used in [Getting started](https://github.com/grpc/grpc-common).
The example code for this and our other examples lives in the `grpc-common`
GitHub repository. Clone this repository to your local machine by running the
following command:
```sh
$ git clone https://github.com/google/grpc-common.git
```
Change your current directory to grpc-common/cpp/helloworld
```sh
$ cd grpc-common/cpp/helloworld/
```
### Generating gRPC code
To generate the client and server side interfaces:
```sh
$ make helloworld.pb.cc
```
Which internally invokes the proto-compiler as:
```sh
$protoc -I ../../protos/ --cpp_out=. --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin helloworld.proto
```
### Client and server implementations
The client implementation is at [greeter_client.cc](https://github.com/grpc/grpc-common/blob/master/cpp/helloworld/greeter_client.cc).
The server implementation is at [greeter_server.cc](https://github.com/grpc/grpc-common/blob/master/cpp/helloworld/greeter_server.cc).
### Try it!
###TODO: instructions to run server and client
## Tutorial
You can find a more detailed tutorial in [gRPC Basics: C++](https://github.com/grpc/grpc-common/blob/master/cpp/cpptutorial.md)

@ -0,0 +1,130 @@
#gRPC Basics: C++
This tutorial provides a basic C++ programmer's introduction to working with gRPC. By walking through this example you'll learn how to:
- Define a service in a .proto file.
- Generate server and client code using the protocol buffer compiler.
- Use the C++ gRPC API to write a simple client and server for your service.
It assumes that you have read the [Getting started](https://github.com/grpc/grpc-common) guide and are familiar with [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial uses the proto3 version of the protocol buffers language, which is currently in alpha release: you can see the [release notes](https://github.com/google/protobuf/releases) for the new version in the protocol buffers Github repository.
This isn't a comprehensive guide to using gRPC in C++: more reference documentation is coming soon.
## Why use gRPC?
Our example is a simple route mapping application that lets clients get information about features on their route, create a summary of their route, and exchange route information such as traffic updates with the server and other clients.
With gRPC we can define our service once in a .proto file and implement clients and servers in any of gRPC's supported languages, which in turn can be run in environments ranging from servers inside Google to your own tablet - all the complexity of communication between different languages and environments is handled for you by gRPC. We also get all the advantages of working with protocol buffers, including efficient serialization, a simple IDL, and easy interface updating.
[possibly insert more advantages here]
## Example code and setup
The example code for our tutorial is in [grpc/grpc-common/cpp/route_guide](https://github.com/grpc/grpc-common/cpp/route_guide). To download the example, clone the `grpc-common` repository by running the following command:
```shell
$ git clone https://github.com/google/grpc-common.git
```
Then change your current directory to `grpc-common/cpp/route_guide`:
```shell
$ cd grpc-common/cpp/route_guide
```
Although we've provided the complete example so you don't need to generate the gRPC code yourself, if you want to try generating your own server and client interface code you can follow the setup instructions for the C++ gRPC libraries in [grpc/grpc/INSTALL](https://github.com/grpc/grpc/blob/master/INSTALL).
## Defining the service
Our first step (as you'll know from [Getting started](https://github.com/grpc/grpc-common)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`grpc-common/protos/route_guide.proto`](https://github.com/grpc/grpc-common/blob/master/protos/route_guide.proto).
To define a service, you specify a named `service` in your .proto file:
```
service RouteGuide {
...
}
```
Then you define `rpc` methods inside your service definition, specifying their request and response types. gRPC lets you define four kinds of service method, all of which are used in the `RouteGuide` service:
- A *simple RPC* where the client sends a request to the server using the stub and waits for a response to come back, just like a normal function call.
```
// Obtains the feature at a given position.
rpc GetFeature(Point) returns (Feature) {}
```
- A *server-side streaming RPC* where the client sends a request to the server and gets a stream to read a sequence of messages back. The client reads from the returned stream until there are no more messages. As you can see in our example, you specify a server-side streaming method by placing the `stream` keyword before the *response* type.
```
// Obtains the Features available within the given Rectangle. Results are
// streamed rather than returned at once (e.g. in a response message with a
// repeated field), as the rectangle may cover a large area and contain a
// huge number of features.
rpc ListFeatures(Rectangle) returns (stream Feature) {}
```
- A *client-side streaming RPC* where the client writes a sequence of messages and sends them to the server, again using a provided stream. Once the client has finished writing the messages, it waits for the server to read them all and return its response. You specify a server-side streaming method by placing the `stream` keyword before the *request* type.
```
// Accepts a stream of Points on a route being traversed, returning a
// RouteSummary when traversal is completed.
rpc RecordRoute(stream Point) returns (RouteSummary) {}
```
- A *bidirectional streaming RPC* where both sides send a sequence of messages using a read-write stream. The two streams operate independently, so clients and servers can read and write in whatever order they like: for example, the server could wait to receive all the client messages before writing its responses, or it could alternately read a message then write a message, or some other combination of reads and writes. The order of messages in each stream is preserved. You specify this type of method by placing the `stream` keyword before both the request and the response.
```
// Accepts a stream of RouteNotes sent while a route is being traversed,
// while receiving other RouteNotes (e.g. from other users).
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
```
Our .proto file also contains protocol buffer message type definitions for all the request and response types used in our service methods - for example, here's the `Point` message type:
```
// Points are represented as latitude-longitude pairs in the E7 representation
// (degrees multiplied by 10**7 and rounded to the nearest integer).
// Latitudes should be in the range +/- 90 degrees and longitude should be in
// the range +/- 180 degrees (inclusive).
message Point {
int32 latitude = 1;
int32 longitude = 2;
}
```
## Generating client and server code
Next we need to generate the gRPC client and server interfaces from our .proto service definition. We do this using the protocol buffer compiler `protoc` with a special gRPC C++ plugin.
For simplicity, we've provided a [makefile](https://github.com/grpc/grpc-common/blob/master/cpp/route_guide/Makefile) that runs `protoc` for you with the appropriate plugin, input, and output (if you want to run this yourself, make sure you've followed the [installation instructions](https://github.com/grpc/grpc/blob/master/INSTALL) first):
```shell
$ make route_guide.pb.cc
```
which actually runs:
[actual command]
Running this command generates the following files:
- `route_guide.pb.h`, the header which declares your generated classes
- `route_guide.pb.cc`, which contains the implementation of your classes
These contain:
- All the protocol buffer code to populate, serialize, and retrieve our request and response message types
- A class called `RouteGuide` that contains both a remote interface type (or *stub*) for clients to call and an abstract interface for servers to implement, both with the methods defined in the `RouteGuide` service.
## Creating the server
First let's look at how we create a `RouteGuide` server.
There are two parts to making our `RouteGuide` service work:
- Implementing the service interface generated from our service definition: doing the actual "work" of our service.
- Running a gRPC server to listen for requests from clients and return the service responses
## Creating the client

@ -0,0 +1,110 @@
#
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
CXX = g++
CPPFLAGS = -I/usr/local/include -pthread
CXXFLAGS = -std=c++11
LDFLAGS = -L/usr/local/lib -lgrpc -lgrpc++ -lprotobuf -lpthread -ldl
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 greeter_client.o
$(CXX) $^ $(LDFLAGS) -o $@
greeter_server: helloworld.pb.o greeter_server.o
$(CXX) $^ $(LDFLAGS) -o $@
%.pb.cc: %.proto
$(PROTOC) -I $(PROTOS_PATH) --cpp_out=. --grpc_out=. --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN_PATH) $<
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-alpha-1"
@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,95 @@
# gRPC C++ Hello World Tutorial
### Install gRPC
Make sure you have installed gRPC on your system. Follow the instructions here:
[https://github.com/grpc/grpc/blob/master/INSTALL](https://github.com/grpc/grpc/blob/master/INSTALL).
### Get the tutorial source code
The example code for this and our other examples lives in the `grpc-common`
GitHub repository. Clone this repository to your local machine by running the
following command:
```sh
$ git clone https://github.com/google/grpc-common.git
```
Change your current directory to grpc-common/cpp/helloworld
```sh
$ cd grpc-common/cpp/helloworld/
```
### Defining a service
The first step in creating our example is to define a *service*: an RPC
service specifies the methods that can be called remotely with their parameters
and return types. As you saw in the
[overview](#protocolbuffers) above, gRPC does this using [protocol
buffers](https://developers.google.com/protocol-buffers/docs/overview). We
use the protocol buffers interface definition language (IDL) to define our
service methods, and define the parameters and return
types as protocol buffer message types. Both the client and the
server use interface code generated from the service definition.
Here's our example service definition, defined using protocol buffers IDL in
[helloworld.proto](https://github.com/grpc/grpc-common/blob/master/protos/helloworld.proto). The `Greeting`
service has one method, `hello`, that lets the server receive a single
`HelloRequest`
message from the remote client containing the user's name, then send back
a greeting in a single `HelloReply`. This is the simplest type of RPC you
can specify in gRPC - we'll look at some other types later in this document.
```
syntax = "proto3";
option java_package = "ex.grpc";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
```
<a name="generating"></a>
### Generating gRPC code
Once we've defined our service, we use the protocol buffer compiler
`protoc` to generate the special client and server code we need to create
our application. The generated code contains both stub code for clients to
use and an abstract interface for servers to implement, both with the method
defined in our `Greeting` service.
To generate the client and server side interfaces:
```sh
$ make helloworld.pb.cc
```
Which internally invokes the proto-compiler as:
```sh
$protoc -I ../../protos/ --cpp_out=. --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin helloworld.proto
```
### Writing a client
This is an incomplete tutorial. For now the reader should refer to [greeter_client.cc](https://github.com/grpc/grpc-common/blob/master/cpp/helloworld/greeter_client.cc).
### Writing a server
This is an incomplete tutorial. For now the reader should refer to [greeter_server.cc](https://github.com/grpc/grpc-common/blob/master/cpp/helloworld/greeter_server.cc).

@ -0,0 +1,91 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <iostream>
#include <memory>
#include <string>
#include <grpc/grpc.h>
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/status.h>
#include "helloworld.pb.h"
using grpc::ChannelArguments;
using grpc::ChannelInterface;
using grpc::ClientContext;
using grpc::Status;
using helloworld::HelloRequest;
using helloworld::HelloReply;
using helloworld::Greeter;
class GreeterClient {
public:
GreeterClient(std::shared_ptr<ChannelInterface> channel)
: stub_(Greeter::NewStub(channel)) {}
std::string SayHello(const std::string& user) {
HelloRequest request;
request.set_name(user);
HelloReply reply;
ClientContext context;
Status status = stub_->SayHello(&context, request, &reply);
if (status.IsOk()) {
return reply.message();
} else {
return "Rpc failed";
}
}
void Shutdown() { stub_.reset(); }
private:
std::unique_ptr<Greeter::Stub> stub_;
};
int main(int argc, char** argv) {
grpc_init();
GreeterClient greeter(
grpc::CreateChannel("localhost:50051", ChannelArguments()));
std::string user("world");
std::string reply = greeter.SayHello(user);
std::cout << "Greeter received: " << reply << std::endl;
greeter.Shutdown();
grpc_shutdown();
}

@ -0,0 +1,84 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include <grpc/grpc.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/status.h>
#include "helloworld.pb.h"
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using helloworld::HelloRequest;
using helloworld::HelloReply;
using helloworld::Greeter;
class GreeterServiceImpl final : public Greeter::Service {
Status SayHello(ServerContext* context, const HelloRequest* request,
HelloReply* reply) override {
std::string prefix("Hello ");
reply->set_message(prefix + request->name());
return Status::OK;
}
};
void RunServer() {
std::string server_address("0.0.0.0:50051");
GreeterServiceImpl service;
ServerBuilder builder;
builder.AddPort(server_address);
builder.RegisterService(&service);
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(5));
}
}
int main(int argc, char** argv) {
grpc_init();
RunServer();
grpc_shutdown();
return 0;
}

@ -0,0 +1,640 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: helloworld.proto
#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
#include "helloworld.pb.h"
#include <algorithm>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/wire_format.h>
#include <grpc++/async_unary_call.h>
#include <grpc++/channel_interface.h>
#include <grpc++/impl/client_unary_call.h>
#include <grpc++/impl/rpc_method.h>
#include <grpc++/impl/rpc_service_method.h>
#include <grpc++/impl/service_type.h>
#include <grpc++/stream.h>
// @@protoc_insertion_point(includes)
namespace helloworld {
namespace {
const ::google::protobuf::Descriptor* HelloRequest_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
HelloRequest_reflection_ = NULL;
const ::google::protobuf::Descriptor* HelloReply_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
HelloReply_reflection_ = NULL;
} // namespace
void protobuf_AssignDesc_helloworld_2eproto() {
protobuf_AddDesc_helloworld_2eproto();
const ::google::protobuf::FileDescriptor* file =
::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
"helloworld.proto");
GOOGLE_CHECK(file != NULL);
HelloRequest_descriptor_ = file->message_type(0);
static const int HelloRequest_offsets_[1] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(HelloRequest, name_),
};
HelloRequest_reflection_ =
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
HelloRequest_descriptor_,
HelloRequest::default_instance_,
HelloRequest_offsets_,
-1,
-1,
-1,
sizeof(HelloRequest),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(HelloRequest, _internal_metadata_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(HelloRequest, _is_default_instance_));
HelloReply_descriptor_ = file->message_type(1);
static const int HelloReply_offsets_[1] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(HelloReply, message_),
};
HelloReply_reflection_ =
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
HelloReply_descriptor_,
HelloReply::default_instance_,
HelloReply_offsets_,
-1,
-1,
-1,
sizeof(HelloReply),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(HelloReply, _internal_metadata_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(HelloReply, _is_default_instance_));
}
namespace {
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
inline void protobuf_AssignDescriptorsOnce() {
::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
&protobuf_AssignDesc_helloworld_2eproto);
}
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
HelloRequest_descriptor_, &HelloRequest::default_instance());
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
HelloReply_descriptor_, &HelloReply::default_instance());
}
} // namespace
void protobuf_ShutdownFile_helloworld_2eproto() {
delete HelloRequest::default_instance_;
delete HelloRequest_reflection_;
delete HelloReply::default_instance_;
delete HelloReply_reflection_;
}
void protobuf_AddDesc_helloworld_2eproto() {
static bool already_here = false;
if (already_here) return;
already_here = true;
GOOGLE_PROTOBUF_VERIFY_VERSION;
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n\020helloworld.proto\022\nhelloworld\"\034\n\014HelloR"
"equest\022\014\n\004name\030\001 \001(\t\"\035\n\nHelloReply\022\017\n\007me"
"ssage\030\001 \001(\t2I\n\007Greeter\022>\n\010SayHello\022\030.hel"
"loworld.HelloRequest\032\026.helloworld.HelloR"
"eply\"\000B\t\n\007ex.grpcb\006proto3", 185);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"helloworld.proto", &protobuf_RegisterTypes);
HelloRequest::default_instance_ = new HelloRequest();
HelloReply::default_instance_ = new HelloReply();
HelloRequest::default_instance_->InitAsDefaultInstance();
HelloReply::default_instance_->InitAsDefaultInstance();
::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_helloworld_2eproto);
}
// Force AddDescriptors() to be called at static initialization time.
struct StaticDescriptorInitializer_helloworld_2eproto {
StaticDescriptorInitializer_helloworld_2eproto() {
protobuf_AddDesc_helloworld_2eproto();
}
} static_descriptor_initializer_helloworld_2eproto_;
namespace {
static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
static void MergeFromFail(int line) {
GOOGLE_CHECK(false) << __FILE__ << ":" << line;
}
} // namespace
// ===================================================================
#ifndef _MSC_VER
const int HelloRequest::kNameFieldNumber;
#endif // !_MSC_VER
HelloRequest::HelloRequest()
: ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:helloworld.HelloRequest)
}
void HelloRequest::InitAsDefaultInstance() {
_is_default_instance_ = true;
}
HelloRequest::HelloRequest(const HelloRequest& from)
: ::google::protobuf::Message(),
_internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:helloworld.HelloRequest)
}
void HelloRequest::SharedCtor() {
_is_default_instance_ = false;
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
HelloRequest::~HelloRequest() {
// @@protoc_insertion_point(destructor:helloworld.HelloRequest)
SharedDtor();
}
void HelloRequest::SharedDtor() {
name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (this != default_instance_) {
}
}
void HelloRequest::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* HelloRequest::descriptor() {
protobuf_AssignDescriptorsOnce();
return HelloRequest_descriptor_;
}
const HelloRequest& HelloRequest::default_instance() {
if (default_instance_ == NULL) protobuf_AddDesc_helloworld_2eproto();
return *default_instance_;
}
HelloRequest* HelloRequest::default_instance_ = NULL;
HelloRequest* HelloRequest::New(::google::protobuf::Arena* arena) const {
HelloRequest* n = new HelloRequest;
if (arena != NULL) {
arena->Own(n);
}
return n;
}
void HelloRequest::Clear() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
bool HelloRequest::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:helloworld.HelloRequest)
for (;;) {
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
tag = p.first;
if (!p.second) goto handle_unusual;
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string name = 1;
case 1: {
if (tag == 10) {
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_name()));
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::PARSE,
"helloworld.HelloRequest.name");
} else {
goto handle_unusual;
}
if (input->ExpectAtEnd()) goto success;
break;
}
default: {
handle_unusual:
if (tag == 0 ||
::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
goto success;
}
DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
break;
}
}
}
success:
// @@protoc_insertion_point(parse_success:helloworld.HelloRequest)
return true;
failure:
// @@protoc_insertion_point(parse_failure:helloworld.HelloRequest)
return false;
#undef DO_
}
void HelloRequest::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
// @@protoc_insertion_point(serialize_start:helloworld.HelloRequest)
// optional string name = 1;
if (this->name().size() > 0) {
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
"helloworld.HelloRequest.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name(), output);
}
// @@protoc_insertion_point(serialize_end:helloworld.HelloRequest)
}
::google::protobuf::uint8* HelloRequest::SerializeWithCachedSizesToArray(
::google::protobuf::uint8* target) const {
// @@protoc_insertion_point(serialize_to_array_start:helloworld.HelloRequest)
// optional string name = 1;
if (this->name().size() > 0) {
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
"helloworld.HelloRequest.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
}
// @@protoc_insertion_point(serialize_to_array_end:helloworld.HelloRequest)
return target;
}
int HelloRequest::ByteSize() const {
int total_size = 0;
// optional string name = 1;
if (this->name().size() > 0) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->name());
}
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
void HelloRequest::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const HelloRequest* source =
::google::protobuf::internal::dynamic_cast_if_available<const HelloRequest*>(
&from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
MergeFrom(*source);
}
}
void HelloRequest::MergeFrom(const HelloRequest& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from.name().size() > 0) {
name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
}
}
void HelloRequest::CopyFrom(const ::google::protobuf::Message& from) {
if (&from == this) return;
Clear();
MergeFrom(from);
}
void HelloRequest::CopyFrom(const HelloRequest& from) {
if (&from == this) return;
Clear();
MergeFrom(from);
}
bool HelloRequest::IsInitialized() const {
return true;
}
void HelloRequest::Swap(HelloRequest* other) {
if (other == this) return;
InternalSwap(other);
}
void HelloRequest::InternalSwap(HelloRequest* other) {
name_.Swap(&other->name_);
_internal_metadata_.Swap(&other->_internal_metadata_);
std::swap(_cached_size_, other->_cached_size_);
}
::google::protobuf::Metadata HelloRequest::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
::google::protobuf::Metadata metadata;
metadata.descriptor = HelloRequest_descriptor_;
metadata.reflection = HelloRequest_reflection_;
return metadata;
}
// ===================================================================
#ifndef _MSC_VER
const int HelloReply::kMessageFieldNumber;
#endif // !_MSC_VER
HelloReply::HelloReply()
: ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:helloworld.HelloReply)
}
void HelloReply::InitAsDefaultInstance() {
_is_default_instance_ = true;
}
HelloReply::HelloReply(const HelloReply& from)
: ::google::protobuf::Message(),
_internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:helloworld.HelloReply)
}
void HelloReply::SharedCtor() {
_is_default_instance_ = false;
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
message_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
HelloReply::~HelloReply() {
// @@protoc_insertion_point(destructor:helloworld.HelloReply)
SharedDtor();
}
void HelloReply::SharedDtor() {
message_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (this != default_instance_) {
}
}
void HelloReply::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* HelloReply::descriptor() {
protobuf_AssignDescriptorsOnce();
return HelloReply_descriptor_;
}
const HelloReply& HelloReply::default_instance() {
if (default_instance_ == NULL) protobuf_AddDesc_helloworld_2eproto();
return *default_instance_;
}
HelloReply* HelloReply::default_instance_ = NULL;
HelloReply* HelloReply::New(::google::protobuf::Arena* arena) const {
HelloReply* n = new HelloReply;
if (arena != NULL) {
arena->Own(n);
}
return n;
}
void HelloReply::Clear() {
message_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
bool HelloReply::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:helloworld.HelloReply)
for (;;) {
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
tag = p.first;
if (!p.second) goto handle_unusual;
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string message = 1;
case 1: {
if (tag == 10) {
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_message()));
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->message().data(), this->message().length(),
::google::protobuf::internal::WireFormat::PARSE,
"helloworld.HelloReply.message");
} else {
goto handle_unusual;
}
if (input->ExpectAtEnd()) goto success;
break;
}
default: {
handle_unusual:
if (tag == 0 ||
::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
goto success;
}
DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
break;
}
}
}
success:
// @@protoc_insertion_point(parse_success:helloworld.HelloReply)
return true;
failure:
// @@protoc_insertion_point(parse_failure:helloworld.HelloReply)
return false;
#undef DO_
}
void HelloReply::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
// @@protoc_insertion_point(serialize_start:helloworld.HelloReply)
// optional string message = 1;
if (this->message().size() > 0) {
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->message().data(), this->message().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
"helloworld.HelloReply.message");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->message(), output);
}
// @@protoc_insertion_point(serialize_end:helloworld.HelloReply)
}
::google::protobuf::uint8* HelloReply::SerializeWithCachedSizesToArray(
::google::protobuf::uint8* target) const {
// @@protoc_insertion_point(serialize_to_array_start:helloworld.HelloReply)
// optional string message = 1;
if (this->message().size() > 0) {
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->message().data(), this->message().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
"helloworld.HelloReply.message");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->message(), target);
}
// @@protoc_insertion_point(serialize_to_array_end:helloworld.HelloReply)
return target;
}
int HelloReply::ByteSize() const {
int total_size = 0;
// optional string message = 1;
if (this->message().size() > 0) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->message());
}
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
void HelloReply::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
const HelloReply* source =
::google::protobuf::internal::dynamic_cast_if_available<const HelloReply*>(
&from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
MergeFrom(*source);
}
}
void HelloReply::MergeFrom(const HelloReply& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
if (from.message().size() > 0) {
message_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.message_);
}
}
void HelloReply::CopyFrom(const ::google::protobuf::Message& from) {
if (&from == this) return;
Clear();
MergeFrom(from);
}
void HelloReply::CopyFrom(const HelloReply& from) {
if (&from == this) return;
Clear();
MergeFrom(from);
}
bool HelloReply::IsInitialized() const {
return true;
}
void HelloReply::Swap(HelloReply* other) {
if (other == this) return;
InternalSwap(other);
}
void HelloReply::InternalSwap(HelloReply* other) {
message_.Swap(&other->message_);
_internal_metadata_.Swap(&other->_internal_metadata_);
std::swap(_cached_size_, other->_cached_size_);
}
::google::protobuf::Metadata HelloReply::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
::google::protobuf::Metadata metadata;
metadata.descriptor = HelloReply_descriptor_;
metadata.reflection = HelloReply_reflection_;
return metadata;
}
static const char* Greeter_method_names[] = {
"/helloworld.Greeter/SayHello",
};
Greeter::Stub* Greeter::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel) {
Greeter::Stub* stub = new Greeter::Stub();
stub->set_channel(channel);
return stub;
};
::grpc::Status Greeter::Stub::SayHello(::grpc::ClientContext* context, const ::helloworld::HelloRequest& request, ::helloworld::HelloReply* response) {
return ::grpc::BlockingUnaryCall(channel(),::grpc::RpcMethod(Greeter_method_names[0]), context, request, response);
}
::grpc::ClientAsyncResponseReader< ::helloworld::HelloReply>* Greeter::Stub::SayHello(::grpc::ClientContext* context, const ::helloworld::HelloRequest& request, ::grpc::CompletionQueue* cq, void* tag) {
return new ::grpc::ClientAsyncResponseReader< ::helloworld::HelloReply>(channel(), cq, ::grpc::RpcMethod(Greeter_method_names[0]), context, request, tag);
}
Greeter::AsyncService::AsyncService(::grpc::CompletionQueue* cq) : ::grpc::AsynchronousService(cq, Greeter_method_names, 1) {}
Greeter::Service::~Service() {
delete service_;
}
::grpc::Status Greeter::Service::SayHello(::grpc::ServerContext* context, const ::helloworld::HelloRequest* request, ::helloworld::HelloReply* response) {
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED);
}
void Greeter::AsyncService::RequestSayHello(::grpc::ServerContext* context, ::helloworld::HelloRequest* request, ::grpc::ServerAsyncResponseWriter< ::helloworld::HelloReply>* response, ::grpc::CompletionQueue* cq, void* tag) {
AsynchronousService::RequestAsyncUnary(0, context, request, response, cq, tag);
}
::grpc::RpcService* Greeter::Service::service() {
if (service_ != nullptr) {
return service_;
}
service_ = new ::grpc::RpcService();
service_->AddMethod(new ::grpc::RpcServiceMethod(
Greeter_method_names[0],
::grpc::RpcMethod::NORMAL_RPC,
new ::grpc::RpcMethodHandler< Greeter::Service, ::helloworld::HelloRequest, ::helloworld::HelloReply>(
std::function< ::grpc::Status(Greeter::Service*, ::grpc::ServerContext*, const ::helloworld::HelloRequest*, ::helloworld::HelloReply*)>(&Greeter::Service::SayHello), this),
new ::helloworld::HelloRequest, new ::helloworld::HelloReply));
return service_;
}
// @@protoc_insertion_point(namespace_scope)
} // namespace helloworld
// @@protoc_insertion_point(global_scope)

@ -0,0 +1,359 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: helloworld.proto
#ifndef PROTOBUF_helloworld_2eproto__INCLUDED
#define PROTOBUF_helloworld_2eproto__INCLUDED
#include <string>
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 3000000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.
#endif
#include <google/protobuf/arena.h>
#include <google/protobuf/arenastring.h>
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/metadata.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/unknown_field_set.h>
#include <grpc++/impl/internal_stub.h>
#include <grpc++/impl/service_type.h>
#include <grpc++/status.h>
namespace grpc {
class CompletionQueue;
class ChannelInterface;
class RpcService;
class ServerContext;
template <class OutMessage> class ClientAsyncResponseReader;
template <class OutMessage> class ServerAsyncResponseWriter;
} // namespace grpc
// @@protoc_insertion_point(includes)
namespace helloworld {
// Internal implementation detail -- do not call these.
void protobuf_AddDesc_helloworld_2eproto();
void protobuf_AssignDesc_helloworld_2eproto();
void protobuf_ShutdownFile_helloworld_2eproto();
class HelloRequest;
class HelloReply;
// ===================================================================
class HelloRequest : public ::google::protobuf::Message {
public:
HelloRequest();
virtual ~HelloRequest();
HelloRequest(const HelloRequest& from);
inline HelloRequest& operator=(const HelloRequest& from) {
CopyFrom(from);
return *this;
}
static const ::google::protobuf::Descriptor* descriptor();
static const HelloRequest& default_instance();
void Swap(HelloRequest* other);
// implements Message ----------------------------------------------
inline HelloRequest* New() const { return New(NULL); }
HelloRequest* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const HelloRequest& from);
void MergeFrom(const HelloRequest& from);
void Clear();
bool IsInitialized() const;
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
void InternalSwap(HelloRequest* other);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
return _internal_metadata_.arena();
}
inline void* MaybeArenaPtr() const {
return _internal_metadata_.raw_arena_ptr();
}
public:
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// optional string name = 1;
inline void clear_name();
static const int kNameFieldNumber = 1;
inline const ::std::string& name() const;
inline void set_name(const ::std::string& value);
inline void set_name(const char* value);
inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
inline ::std::string* release_name();
inline void set_allocated_name(::std::string* name);
// @@protoc_insertion_point(class_scope:helloworld.HelloRequest)
private:
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
bool _is_default_instance_;
::google::protobuf::internal::ArenaStringPtr name_;
mutable int _cached_size_;
friend void protobuf_AddDesc_helloworld_2eproto();
friend void protobuf_AssignDesc_helloworld_2eproto();
friend void protobuf_ShutdownFile_helloworld_2eproto();
void InitAsDefaultInstance();
static HelloRequest* default_instance_;
};
// -------------------------------------------------------------------
class HelloReply : public ::google::protobuf::Message {
public:
HelloReply();
virtual ~HelloReply();
HelloReply(const HelloReply& from);
inline HelloReply& operator=(const HelloReply& from) {
CopyFrom(from);
return *this;
}
static const ::google::protobuf::Descriptor* descriptor();
static const HelloReply& default_instance();
void Swap(HelloReply* other);
// implements Message ----------------------------------------------
inline HelloReply* New() const { return New(NULL); }
HelloReply* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const HelloReply& from);
void MergeFrom(const HelloReply& from);
void Clear();
bool IsInitialized() const;
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
void InternalSwap(HelloReply* other);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
return _internal_metadata_.arena();
}
inline void* MaybeArenaPtr() const {
return _internal_metadata_.raw_arena_ptr();
}
public:
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// optional string message = 1;
inline void clear_message();
static const int kMessageFieldNumber = 1;
inline const ::std::string& message() const;
inline void set_message(const ::std::string& value);
inline void set_message(const char* value);
inline void set_message(const char* value, size_t size);
inline ::std::string* mutable_message();
inline ::std::string* release_message();
inline void set_allocated_message(::std::string* message);
// @@protoc_insertion_point(class_scope:helloworld.HelloReply)
private:
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
bool _is_default_instance_;
::google::protobuf::internal::ArenaStringPtr message_;
mutable int _cached_size_;
friend void protobuf_AddDesc_helloworld_2eproto();
friend void protobuf_AssignDesc_helloworld_2eproto();
friend void protobuf_ShutdownFile_helloworld_2eproto();
void InitAsDefaultInstance();
static HelloReply* default_instance_;
};
// ===================================================================
// ===================================================================
// HelloRequest
// optional string name = 1;
inline void HelloRequest::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& HelloRequest::name() const {
// @@protoc_insertion_point(field_get:helloworld.HelloRequest.name)
return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void HelloRequest::set_name(const ::std::string& value) {
name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:helloworld.HelloRequest.name)
}
inline void HelloRequest::set_name(const char* value) {
name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
// @@protoc_insertion_point(field_set_char:helloworld.HelloRequest.name)
}
inline void HelloRequest::set_name(const char* value, size_t size) {
name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:helloworld.HelloRequest.name)
}
inline ::std::string* HelloRequest::mutable_name() {
// @@protoc_insertion_point(field_mutable:helloworld.HelloRequest.name)
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* HelloRequest::release_name() {
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void HelloRequest::set_allocated_name(::std::string* name) {
if (name != NULL) {
} else {
}
name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
// @@protoc_insertion_point(field_set_allocated:helloworld.HelloRequest.name)
}
// -------------------------------------------------------------------
// HelloReply
// optional string message = 1;
inline void HelloReply::clear_message() {
message_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& HelloReply::message() const {
// @@protoc_insertion_point(field_get:helloworld.HelloReply.message)
return message_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void HelloReply::set_message(const ::std::string& value) {
message_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:helloworld.HelloReply.message)
}
inline void HelloReply::set_message(const char* value) {
message_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
// @@protoc_insertion_point(field_set_char:helloworld.HelloReply.message)
}
inline void HelloReply::set_message(const char* value, size_t size) {
message_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:helloworld.HelloReply.message)
}
inline ::std::string* HelloReply::mutable_message() {
// @@protoc_insertion_point(field_mutable:helloworld.HelloReply.message)
return message_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* HelloReply::release_message() {
return message_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void HelloReply::set_allocated_message(::std::string* message) {
if (message != NULL) {
} else {
}
message_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), message);
// @@protoc_insertion_point(field_set_allocated:helloworld.HelloReply.message)
}
class Greeter final {
public:
class Stub final : public ::grpc::InternalStub {
public:
::grpc::Status SayHello(::grpc::ClientContext* context, const ::helloworld::HelloRequest& request, ::helloworld::HelloReply* response);
::grpc::ClientAsyncResponseReader< ::helloworld::HelloReply>* SayHello(::grpc::ClientContext* context, const ::helloworld::HelloRequest& request, ::grpc::CompletionQueue* cq, void* tag);
};
static Stub* NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel);
class Service : public ::grpc::SynchronousService {
public:
Service() : service_(nullptr) {}
virtual ~Service();
virtual ::grpc::Status SayHello(::grpc::ServerContext* context, const ::helloworld::HelloRequest* request, ::helloworld::HelloReply* response);
::grpc::RpcService* service() override final;
private:
::grpc::RpcService* service_;
};
class AsyncService final : public ::grpc::AsynchronousService {
public:
explicit AsyncService(::grpc::CompletionQueue* cq);
~AsyncService() {};
void RequestSayHello(::grpc::ServerContext* context, ::helloworld::HelloRequest* request, ::grpc::ServerAsyncResponseWriter< ::helloworld::HelloReply>* response, ::grpc::CompletionQueue* cq, void *tag);
};
};
// @@protoc_insertion_point(namespace_scope)
} // namespace helloworld
#ifndef SWIG
namespace google {
namespace protobuf {
} // namespace protobuf
} // namespace google
#endif // SWIG
// @@protoc_insertion_point(global_scope)
#endif // PROTOBUF_helloworld_2eproto__INCLUDED

@ -0,0 +1,49 @@
gRPC in 3 minutes (Go)
======================
PREREQUISITES
-------------
- This requires Go 1.4
- Requires that [GOPATH is set](https://golang.org/doc/code.html#GOPATH)
```sh
$ go help gopath
$ # ensure the PATH contains $GOPATH/bin
$ export PATH=$PATH:$GOPATH/bin
```
INSTALL
-------
```sh
$ go get -u github.com/grpc-common/go/greeter_client
$ go get -u github.com/grpc-common/go/greeter_server
```
TRY IT!
-------
- Run the server
```sh
$ greeter_server &
```
- Run the client
```sh
$ greeter_client
```
OPTIONAL - Rebuilding the generated code
----------------------------------------
1 First [install protoc](https://github.com/google/protobuf/blob/master/INSTALL.txt)
- For now, this needs to be installed from source
- This is will change once proto3 is officially released
2 Install the protoc Go plugin.
```sh
$ go get -a github.com/golang/protobuf/protoc-gen-go
$
$ # from this dir; invoke protoc
$ protoc -I ../protos ../protos/helloworld.proto --go_out=plugins=grpc:.
```

@ -0,0 +1,69 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package main
import (
"log"
"os"
pb "github.com/grpc-common/go/helloworld"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
const (
address = "localhost:50051"
defaultName = "world"
)
func main() {
// Set up a connection to the server.
conn, err := grpc.Dial(address)
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
// Contact the server and print out its response.
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.Message)
}

@ -0,0 +1,65 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package main
import (
"log"
"net"
pb "github.com/grpc-common/go/helloworld"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
const (
port = ":50051"
)
// server is used to implement hellowrld.GreeterServer.
type server struct{}
// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}
func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
s.Serve(lis)
}

@ -0,0 +1,109 @@
// Code generated by protoc-gen-go.
// source: helloworld.proto
// DO NOT EDIT!
/*
Package helloworld is a generated protocol buffer package.
It is generated from these files:
helloworld.proto
It has these top-level messages:
HelloRequest
HelloReply
*/
package helloworld
import proto "github.com/golang/protobuf/proto"
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
// The request message containing the user's name.
type HelloRequest struct {
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
}
func (m *HelloRequest) Reset() { *m = HelloRequest{} }
func (m *HelloRequest) String() string { return proto.CompactTextString(m) }
func (*HelloRequest) ProtoMessage() {}
// The response message containing the greetings
type HelloReply struct {
Message string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"`
}
func (m *HelloReply) Reset() { *m = HelloReply{} }
func (m *HelloReply) String() string { return proto.CompactTextString(m) }
func (*HelloReply) ProtoMessage() {}
func init() {
}
// Client API for Greeter service
type GreeterClient interface {
// Sends a greeting
SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error)
}
type greeterClient struct {
cc *grpc.ClientConn
}
func NewGreeterClient(cc *grpc.ClientConn) GreeterClient {
return &greeterClient{cc}
}
func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) {
out := new(HelloReply)
err := grpc.Invoke(ctx, "/helloworld.Greeter/sayHello", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for Greeter service
type GreeterServer interface {
// Sends a greeting
SayHello(context.Context, *HelloRequest) (*HelloReply, error)
}
func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) {
s.RegisterService(&_Greeter_serviceDesc, srv)
}
func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, buf []byte) (proto.Message, error) {
in := new(HelloRequest)
if err := proto.Unmarshal(buf, in); err != nil {
return nil, err
}
out, err := srv.(GreeterServer).SayHello(ctx, in)
if err != nil {
return nil, err
}
return out, nil
}
var _Greeter_serviceDesc = grpc.ServiceDesc{
ServiceName: "helloworld.Greeter",
HandlerType: (*GreeterServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "sayHello",
Handler: _Greeter_SayHello_Handler,
},
},
Streams: []grpc.StreamDesc{},
}

@ -1,6 +1,6 @@
#!/bin/bash -e #!/bin/bash -e
TARGET='Greetings Client' TARGET='Greeter Client'
TARGET_CLASS='ex.grpc.GreetingsClient' TARGET_CLASS='ex.grpc.GreeterClient'
TARGET_ARGS="$@" TARGET_ARGS="$@"
cd "$(dirname "$0")" cd "$(dirname "$0")"

@ -1,6 +1,6 @@
#!/bin/bash -e #!/bin/bash -e
TARGET='Greetings Server' TARGET='Greeter Server'
TARGET_CLASS='ex.grpc.GreetingsServer' TARGET_CLASS='ex.grpc.GreeterServer'
cd "$(dirname "$0")" cd "$(dirname "$0")"
mvn -q -nsu -am package -Dcheckstyle.skip=true -DskipTests mvn -q -nsu -am package -Dcheckstyle.skip=true -DskipTests

@ -9,17 +9,17 @@ import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class GreetingsClient { public class GreeterClient {
private final Logger logger = Logger.getLogger( private final Logger logger = Logger.getLogger(
GreetingsClient.class.getName()); GreeterClient.class.getName());
private final ChannelImpl channel; private final ChannelImpl channel;
private final GreetingsGrpc.GreetingsBlockingStub blockingStub; private final GreeterGrpc.GreeterBlockingStub blockingStub;
public GreetingsClient(String host, int port) { public GreeterClient(String host, int port) {
channel = NettyChannelBuilder.forAddress(host, port) channel = NettyChannelBuilder.forAddress(host, port)
.negotiationType(NegotiationType.PLAINTEXT) .negotiationType(NegotiationType.PLAINTEXT)
.build(); .build();
blockingStub = GreetingsGrpc.newBlockingStub(channel); blockingStub = GreeterGrpc.newBlockingStub(channel);
} }
public void shutdown() throws InterruptedException { public void shutdown() throws InterruptedException {
@ -31,7 +31,7 @@ public class GreetingsClient {
logger.fine("Will try to greet " + name + " ..."); logger.fine("Will try to greet " + name + " ...");
Helloworld.HelloRequest req = Helloworld.HelloRequest req =
Helloworld.HelloRequest.newBuilder().setName(name).build(); Helloworld.HelloRequest.newBuilder().setName(name).build();
Helloworld.HelloReply reply = blockingStub.hello(req); Helloworld.HelloReply reply = blockingStub.sayHello(req);
logger.info("Greeting: " + reply.getMessage()); logger.info("Greeting: " + reply.getMessage());
} catch (RuntimeException e) { } catch (RuntimeException e) {
logger.log(Level.WARNING, "RPC failed", e); logger.log(Level.WARNING, "RPC failed", e);
@ -40,7 +40,7 @@ public class GreetingsClient {
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
GreetingsClient client = new GreetingsClient("localhost", 50051); GreeterClient client = new GreeterClient("localhost", 50051);
try { try {
/* Access a service running on the local machine on port 50051 */ /* Access a service running on the local machine on port 50051 */
String user = "world"; String user = "world";

@ -13,150 +13,150 @@ import static com.google.net.stubby.stub.ServerCalls.asyncUnaryRequestCall;
import static com.google.net.stubby.stub.ServerCalls.asyncStreamingRequestCall; import static com.google.net.stubby.stub.ServerCalls.asyncStreamingRequestCall;
@javax.annotation.Generated("by gRPC proto compiler") @javax.annotation.Generated("by gRPC proto compiler")
public class GreetingsGrpc { public class GreeterGrpc {
private static final com.google.net.stubby.stub.Method<ex.grpc.Helloworld.HelloRequest, private static final com.google.net.stubby.stub.Method<ex.grpc.Helloworld.HelloRequest,
ex.grpc.Helloworld.HelloReply> METHOD_HELLO = ex.grpc.Helloworld.HelloReply> METHOD_SAY_HELLO =
com.google.net.stubby.stub.Method.create( com.google.net.stubby.stub.Method.create(
com.google.net.stubby.MethodType.UNARY, "hello", com.google.net.stubby.MethodType.UNARY, "sayHello",
com.google.net.stubby.proto.ProtoUtils.marshaller(ex.grpc.Helloworld.HelloRequest.PARSER), com.google.net.stubby.proto.ProtoUtils.marshaller(ex.grpc.Helloworld.HelloRequest.PARSER),
com.google.net.stubby.proto.ProtoUtils.marshaller(ex.grpc.Helloworld.HelloReply.PARSER)); com.google.net.stubby.proto.ProtoUtils.marshaller(ex.grpc.Helloworld.HelloReply.PARSER));
public static GreetingsStub newStub(com.google.net.stubby.Channel channel) { public static GreeterStub newStub(com.google.net.stubby.Channel channel) {
return new GreetingsStub(channel, CONFIG); return new GreeterStub(channel, CONFIG);
} }
public static GreetingsBlockingStub newBlockingStub( public static GreeterBlockingStub newBlockingStub(
com.google.net.stubby.Channel channel) { com.google.net.stubby.Channel channel) {
return new GreetingsBlockingStub(channel, CONFIG); return new GreeterBlockingStub(channel, CONFIG);
} }
public static GreetingsFutureStub newFutureStub( public static GreeterFutureStub newFutureStub(
com.google.net.stubby.Channel channel) { com.google.net.stubby.Channel channel) {
return new GreetingsFutureStub(channel, CONFIG); return new GreeterFutureStub(channel, CONFIG);
} }
public static final GreetingsServiceDescriptor CONFIG = public static final GreeterServiceDescriptor CONFIG =
new GreetingsServiceDescriptor(); new GreeterServiceDescriptor();
@javax.annotation.concurrent.Immutable @javax.annotation.concurrent.Immutable
public static class GreetingsServiceDescriptor extends public static class GreeterServiceDescriptor extends
com.google.net.stubby.stub.AbstractServiceDescriptor<GreetingsServiceDescriptor> { com.google.net.stubby.stub.AbstractServiceDescriptor<GreeterServiceDescriptor> {
public final com.google.net.stubby.MethodDescriptor<ex.grpc.Helloworld.HelloRequest, public final com.google.net.stubby.MethodDescriptor<ex.grpc.Helloworld.HelloRequest,
ex.grpc.Helloworld.HelloReply> hello; ex.grpc.Helloworld.HelloReply> sayHello;
private GreetingsServiceDescriptor() { private GreeterServiceDescriptor() {
hello = createMethodDescriptor( sayHello = createMethodDescriptor(
"helloworld.Greetings", METHOD_HELLO); "helloworld.Greeter", METHOD_SAY_HELLO);
} }
private GreetingsServiceDescriptor( private GreeterServiceDescriptor(
java.util.Map<java.lang.String, com.google.net.stubby.MethodDescriptor<?, ?>> methodMap) { java.util.Map<java.lang.String, com.google.net.stubby.MethodDescriptor<?, ?>> methodMap) {
hello = (com.google.net.stubby.MethodDescriptor<ex.grpc.Helloworld.HelloRequest, sayHello = (com.google.net.stubby.MethodDescriptor<ex.grpc.Helloworld.HelloRequest,
ex.grpc.Helloworld.HelloReply>) methodMap.get( ex.grpc.Helloworld.HelloReply>) methodMap.get(
CONFIG.hello.getName()); CONFIG.sayHello.getName());
} }
@java.lang.Override @java.lang.Override
protected GreetingsServiceDescriptor build( protected GreeterServiceDescriptor build(
java.util.Map<java.lang.String, com.google.net.stubby.MethodDescriptor<?, ?>> methodMap) { java.util.Map<java.lang.String, com.google.net.stubby.MethodDescriptor<?, ?>> methodMap) {
return new GreetingsServiceDescriptor(methodMap); return new GreeterServiceDescriptor(methodMap);
} }
@java.lang.Override @java.lang.Override
public com.google.common.collect.ImmutableList<com.google.net.stubby.MethodDescriptor<?, ?>> methods() { public com.google.common.collect.ImmutableList<com.google.net.stubby.MethodDescriptor<?, ?>> methods() {
return com.google.common.collect.ImmutableList.<com.google.net.stubby.MethodDescriptor<?, ?>>of( return com.google.common.collect.ImmutableList.<com.google.net.stubby.MethodDescriptor<?, ?>>of(
hello); sayHello);
} }
} }
public static interface Greetings { public static interface Greeter {
public void hello(ex.grpc.Helloworld.HelloRequest request, public void sayHello(ex.grpc.Helloworld.HelloRequest request,
com.google.net.stubby.stub.StreamObserver<ex.grpc.Helloworld.HelloReply> responseObserver); com.google.net.stubby.stub.StreamObserver<ex.grpc.Helloworld.HelloReply> responseObserver);
} }
public static interface GreetingsBlockingClient { public static interface GreeterBlockingClient {
public ex.grpc.Helloworld.HelloReply hello(ex.grpc.Helloworld.HelloRequest request); public ex.grpc.Helloworld.HelloReply sayHello(ex.grpc.Helloworld.HelloRequest request);
} }
public static interface GreetingsFutureClient { public static interface GreeterFutureClient {
public com.google.common.util.concurrent.ListenableFuture<ex.grpc.Helloworld.HelloReply> hello( public com.google.common.util.concurrent.ListenableFuture<ex.grpc.Helloworld.HelloReply> sayHello(
ex.grpc.Helloworld.HelloRequest request); ex.grpc.Helloworld.HelloRequest request);
} }
public static class GreetingsStub extends public static class GreeterStub extends
com.google.net.stubby.stub.AbstractStub<GreetingsStub, GreetingsServiceDescriptor> com.google.net.stubby.stub.AbstractStub<GreeterStub, GreeterServiceDescriptor>
implements Greetings { implements Greeter {
private GreetingsStub(com.google.net.stubby.Channel channel, private GreeterStub(com.google.net.stubby.Channel channel,
GreetingsServiceDescriptor config) { GreeterServiceDescriptor config) {
super(channel, config); super(channel, config);
} }
@java.lang.Override @java.lang.Override
protected GreetingsStub build(com.google.net.stubby.Channel channel, protected GreeterStub build(com.google.net.stubby.Channel channel,
GreetingsServiceDescriptor config) { GreeterServiceDescriptor config) {
return new GreetingsStub(channel, config); return new GreeterStub(channel, config);
} }
@java.lang.Override @java.lang.Override
public void hello(ex.grpc.Helloworld.HelloRequest request, public void sayHello(ex.grpc.Helloworld.HelloRequest request,
com.google.net.stubby.stub.StreamObserver<ex.grpc.Helloworld.HelloReply> responseObserver) { com.google.net.stubby.stub.StreamObserver<ex.grpc.Helloworld.HelloReply> responseObserver) {
asyncUnaryCall( asyncUnaryCall(
channel.newCall(config.hello), request, responseObserver); channel.newCall(config.sayHello), request, responseObserver);
} }
} }
public static class GreetingsBlockingStub extends public static class GreeterBlockingStub extends
com.google.net.stubby.stub.AbstractStub<GreetingsBlockingStub, GreetingsServiceDescriptor> com.google.net.stubby.stub.AbstractStub<GreeterBlockingStub, GreeterServiceDescriptor>
implements GreetingsBlockingClient { implements GreeterBlockingClient {
private GreetingsBlockingStub(com.google.net.stubby.Channel channel, private GreeterBlockingStub(com.google.net.stubby.Channel channel,
GreetingsServiceDescriptor config) { GreeterServiceDescriptor config) {
super(channel, config); super(channel, config);
} }
@java.lang.Override @java.lang.Override
protected GreetingsBlockingStub build(com.google.net.stubby.Channel channel, protected GreeterBlockingStub build(com.google.net.stubby.Channel channel,
GreetingsServiceDescriptor config) { GreeterServiceDescriptor config) {
return new GreetingsBlockingStub(channel, config); return new GreeterBlockingStub(channel, config);
} }
@java.lang.Override @java.lang.Override
public ex.grpc.Helloworld.HelloReply hello(ex.grpc.Helloworld.HelloRequest request) { public ex.grpc.Helloworld.HelloReply sayHello(ex.grpc.Helloworld.HelloRequest request) {
return blockingUnaryCall( return blockingUnaryCall(
channel.newCall(config.hello), request); channel.newCall(config.sayHello), request);
} }
} }
public static class GreetingsFutureStub extends public static class GreeterFutureStub extends
com.google.net.stubby.stub.AbstractStub<GreetingsFutureStub, GreetingsServiceDescriptor> com.google.net.stubby.stub.AbstractStub<GreeterFutureStub, GreeterServiceDescriptor>
implements GreetingsFutureClient { implements GreeterFutureClient {
private GreetingsFutureStub(com.google.net.stubby.Channel channel, private GreeterFutureStub(com.google.net.stubby.Channel channel,
GreetingsServiceDescriptor config) { GreeterServiceDescriptor config) {
super(channel, config); super(channel, config);
} }
@java.lang.Override @java.lang.Override
protected GreetingsFutureStub build(com.google.net.stubby.Channel channel, protected GreeterFutureStub build(com.google.net.stubby.Channel channel,
GreetingsServiceDescriptor config) { GreeterServiceDescriptor config) {
return new GreetingsFutureStub(channel, config); return new GreeterFutureStub(channel, config);
} }
@java.lang.Override @java.lang.Override
public com.google.common.util.concurrent.ListenableFuture<ex.grpc.Helloworld.HelloReply> hello( public com.google.common.util.concurrent.ListenableFuture<ex.grpc.Helloworld.HelloReply> sayHello(
ex.grpc.Helloworld.HelloRequest request) { ex.grpc.Helloworld.HelloRequest request) {
return unaryFutureCall( return unaryFutureCall(
channel.newCall(config.hello), request); channel.newCall(config.sayHello), request);
} }
} }
public static com.google.net.stubby.ServerServiceDefinition bindService( public static com.google.net.stubby.ServerServiceDefinition bindService(
final Greetings serviceImpl) { final Greeter serviceImpl) {
return com.google.net.stubby.ServerServiceDefinition.builder("helloworld.Greetings") return com.google.net.stubby.ServerServiceDefinition.builder("helloworld.Greeter")
.addMethod(createMethodDefinition( .addMethod(createMethodDefinition(
METHOD_HELLO, METHOD_SAY_HELLO,
asyncUnaryRequestCall( asyncUnaryRequestCall(
new com.google.net.stubby.stub.ServerCalls.UnaryRequestMethod< new com.google.net.stubby.stub.ServerCalls.UnaryRequestMethod<
ex.grpc.Helloworld.HelloRequest, ex.grpc.Helloworld.HelloRequest,
@ -165,7 +165,7 @@ public class GreetingsGrpc {
public void invoke( public void invoke(
ex.grpc.Helloworld.HelloRequest request, ex.grpc.Helloworld.HelloRequest request,
com.google.net.stubby.stub.StreamObserver<ex.grpc.Helloworld.HelloReply> responseObserver) { com.google.net.stubby.stub.StreamObserver<ex.grpc.Helloworld.HelloReply> responseObserver) {
serviceImpl.hello(request, responseObserver); serviceImpl.sayHello(request, responseObserver);
} }
}))).build(); }))).build();
} }

@ -2,10 +2,10 @@ package ex.grpc;
import com.google.net.stubby.stub.StreamObserver; import com.google.net.stubby.stub.StreamObserver;
public class GreetingsImpl implements GreetingsGrpc.Greetings { public class GreeterImpl implements GreeterGrpc.Greeter {
@Override @Override
public void hello(Helloworld.HelloRequest req, public void sayHello(Helloworld.HelloRequest req,
StreamObserver<Helloworld.HelloReply> responseObserver) { StreamObserver<Helloworld.HelloReply> responseObserver) {
Helloworld.HelloReply reply = Helloworld.HelloReply.newBuilder().setMessage( Helloworld.HelloReply reply = Helloworld.HelloReply.newBuilder().setMessage(
"Hello " + req.getName()).build(); "Hello " + req.getName()).build();

@ -7,16 +7,16 @@ import com.google.net.stubby.transport.netty.NettyServerBuilder;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
* Server that manages startup/shutdown of a {@code Greetings} server. * Server that manages startup/shutdown of a {@code Greeter} server.
*/ */
public class GreetingsServer { public class GreeterServer {
/* The port on which the server should run */ /* The port on which the server should run */
private int port = 50051; private int port = 50051;
private ServerImpl server; private ServerImpl server;
private void start() throws Exception { private void start() throws Exception {
server = NettyServerBuilder.forPort(port) server = NettyServerBuilder.forPort(port)
.addService(GreetingsGrpc.bindService(new GreetingsImpl())) .addService(GreeterGrpc.bindService(new GreeterImpl()))
.build(); .build();
server.startAsync(); server.startAsync();
server.awaitRunning(5, TimeUnit.SECONDS); server.awaitRunning(5, TimeUnit.SECONDS);
@ -33,7 +33,7 @@ public class GreetingsServer {
* Main launches the server from the command line. * Main launches the server from the command line.
*/ */
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
final GreetingsServer server = new GreetingsServer(); final GreeterServer server = new GreeterServer();
Runtime.getRuntime().addShutdownHook(new Thread() { Runtime.getRuntime().addShutdownHook(new Thread() {
@Override @Override

@ -1,5 +1,5 @@
// Generated by the protocol buffer compiler. DO NOT EDIT! // Generated by the protocol buffer compiler. DO NOT EDIT!
// source: src/main/proto/helloworld.proto // source: helloworld.proto
package ex.grpc; package ex.grpc;
@ -915,11 +915,11 @@ public final class Helloworld {
descriptor; descriptor;
static { static {
java.lang.String[] descriptorData = { java.lang.String[] descriptorData = {
"\n\037src/main/proto/helloworld.proto\022\nhello" + "\n\020helloworld.proto\022\nhelloworld\"\034\n\014HelloR" +
"world\"\034\n\014HelloRequest\022\014\n\004name\030\001 \001(\t\"\035\n\nH" + "equest\022\014\n\004name\030\001 \001(\t\"\035\n\nHelloReply\022\017\n\007me" +
"elloReply\022\017\n\007message\030\001 \001(\t2H\n\tGreetings\022" + "ssage\030\001 \001(\t2I\n\007Greeter\022>\n\010sayHello\022\030.hel" +
";\n\005hello\022\030.helloworld.HelloRequest\032\026.hel" + "loworld.HelloRequest\032\026.helloworld.HelloR" +
"loworld.HelloReply\"\000B\t\n\007ex.grpcb\006proto3" "eply\"\000B\t\n\007ex.grpcb\006proto3"
}; };
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {

3
node/.gitignore vendored

@ -0,0 +1,3 @@
*~
node_modules
npm-debug.log

@ -0,0 +1,38 @@
gRPC in 3 minutes (Node.js)
===========================
PREREQUISITES
-------------
This requires Node 10.x or greater.
INSTALL
-------
- Clone this repository
- Follow the instructions in [INSTALL](https://github.com/grpc/grpc/blob/master/INSTALL) to install the gRPC C core.
- Run `npm install` to install dependencies
- If `grpc` is not found, clone the [gRPC](https://github.com/grpc/grpc) repository and run `npm install path/to/grpc/src/node`.
Try it!
-------
- Run the server
```sh
$ # from this directory
$ nodejs ./greeter_server.js &
```
- Run the client
```sh
$ # from this directory
$ nodejs ./greeter_client.js
```
Note
----
This directory has a copy of `helloworld.proto` because it currently depends on
some Protocol Buffer 2.0 syntax that is deprecated in Protocol Buffer 3.0.

@ -0,0 +1,52 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
var PROTO_PATH = __dirname + '/helloworld.proto';
var grpc = require('grpc');
var hello_proto = grpc.load(PROTO_PATH).helloworld;
function main() {
var client = new hello_proto.Greeter('localhost:50051');
var user;
if (process.argv.length >= 3) {
user = process.argv[2];
} else {
user = 'world';
}
client.sayHello({name: user}, function(err, response) {
console.log('Greeting:', response.message);
});
}
main();

@ -0,0 +1,63 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
var PROTO_PATH = __dirname + '/helloworld.proto';
var grpc = require('grpc');
var hello_proto = grpc.load(PROTO_PATH).helloworld;
var Server = grpc.buildServer([hello_proto.Greeter.service]);
/**
* Implements the SayHello RPC method.
*/
function sayHello(call, callback) {
callback(null, {message: 'Hello ' + call.request.name});
}
/**
* Starts an RPC server that receives requests for the Greeter service at the
* sample server port
*/
function main() {
var server = new Server({
"helloworld.Greeter": {
sayHello: sayHello
}
});
server.bind('0.0.0.0:50051');
server.listen();
}
main();

@ -0,0 +1,50 @@
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
option java_package = "ex.grpc";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
optional string name = 1;
}
// The response message containing the greetings
message HelloReply {
optional string message = 1;
}

@ -0,0 +1,10 @@
{
"name": "grpc-greeter",
"version": "0.1.0",
"dependencies": {
"async": "^0.9.0",
"grpc": "~0.2.0",
"minimist": "^1.1.0",
"underscore": "^1.8.2"
}
}

@ -0,0 +1,120 @@
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
option java_package = "io.grpc.examples";
package examples;
// Interface exported by the server.
service RouteGuide {
// A simple RPC.
//
// Obtains the feature at a given position.
rpc GetFeature(Point) returns (Feature) {}
// A server-to-client streaming RPC.
//
// Obtains the Features available within the given Rectangle. Results are
// streamed rather than returned at once (e.g. in a response message with a
// repeated field), as the rectangle may cover a large area and contain a
// huge number of features.
rpc ListFeatures(Rectangle) returns (stream Feature) {}
// A client-to-server streaming RPC.
//
// Accepts a stream of Points on a route being traversed, returning a
// RouteSummary when traversal is completed.
rpc RecordRoute(stream Point) returns (RouteSummary) {}
// A Bidirectional streaming RPC.
//
// Accepts a stream of RouteNotes sent while a route is being traversed,
// while receiving other RouteNotes (e.g. from other users).
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}
// Points are represented as latitude-longitude pairs in the E7 representation
// (degrees multiplied by 10**7 and rounded to the nearest integer).
// Latitudes should be in the range +/- 90 degrees and longitude should be in
// the range +/- 180 degrees (inclusive).
message Point {
optional int32 latitude = 1;
optional int32 longitude = 2;
}
// A latitude-longitude rectangle, represented as two diagonally opposite
// points "lo" and "hi".
message Rectangle {
// One corner of the rectangle.
optional Point lo = 1;
// The other corner of the rectangle.
optional Point hi = 2;
}
// A feature names something at a given point.
//
// If a feature could not be named, the name is empty.
message Feature {
// The name of the feature.
optional string name = 1;
// The point where the feature is detected.
optional Point location = 2;
}
// A RouteNote is a message sent while at a given point.
message RouteNote {
// The location from which the message is sent.
optional Point location = 1;
// The message to be sent.
optional string message = 2;
}
// A RouteSummary is received in response to a RecordRoute rpc.
//
// It contains the number of individual points received, the number of
// detected features, and the total distance covered as the cumulative sum of
// the distance between each point.
message RouteSummary {
// The number of points received.
optional int32 point_count = 1;
// The number of known features passed while traversing the route.
optional int32 feature_count = 2;
// The distance covered in metres.
optional int32 distance = 3;
// The duration of the traversal in seconds.
optional int32 elapsed_time = 4;
}

@ -0,0 +1,231 @@
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
var async = require('async');
var fs = require('fs');
var parseArgs = require('minimist');
var path = require('path');
var _ = require('underscore');
var grpc = require('grpc');
var examples = grpc.load(__dirname + '/route_guide.proto').examples;
var client = new examples.RouteGuide('localhost:50051');
var COORD_FACTOR = 1e7;
/**
* Run the getFeature demo. Calls getFeature with a point known to have a
* feature and a point known not to have a feature.
* @param {function} callback Called when this demo is complete
*/
function runGetFeature(callback) {
var next = _.after(2, callback);
function featureCallback(error, feature) {
if (error) {
callback(error);
}
if (feature.name === '') {
console.log('Found no feature at ' +
feature.location.latitude/COORD_FACTOR + ', ' +
feature.location.longitude/COORD_FACTOR);
} else {
console.log('Found feature called "' + feature.name + '" at ' +
feature.location.latitude/COORD_FACTOR + ', ' +
feature.location.longitude/COORD_FACTOR);
}
next();
}
var point1 = {
latitude: 409146138,
longitude: -746188906
};
var point2 = {
latitude: 0,
longitude: 0
};
client.getFeature(point1, featureCallback);
client.getFeature(point2, featureCallback);
}
/**
* Run the listFeatures demo. Calls listFeatures with a rectangle containing all
* of the features in the pre-generated database. Prints each response as it
* comes in.
* @param {function} callback Called when this demo is complete
*/
function runListFeatures(callback) {
var rectangle = {
lo: {
latitude: 400000000,
longitude: -750000000
},
hi: {
latitude: 420000000,
longitude: -730000000
}
};
console.log('Looking for features between 40, -75 and 42, -73');
var call = client.listFeatures(rectangle);
call.on('data', function(feature) {
console.log('Found feature called "' + feature.name + '" at ' +
feature.location.latitude/COORD_FACTOR + ', ' +
feature.location.longitude/COORD_FACTOR);
});
call.on('end', callback);
}
/**
* Run the recordRoute demo. Sends several randomly chosen points from the
* pre-generated feature database with a variable delay in between. Prints the
* statistics when they are sent from the server.
* @param {function} callback Called when this demo is complete
*/
function runRecordRoute(callback) {
var argv = parseArgs(process.argv, {
string: 'db_path'
});
fs.readFile(path.resolve(argv.db_path), function(err, data) {
if (err) callback(err);
var feature_list = JSON.parse(data);
var num_points = 10;
var call = client.recordRoute(function(error, stats) {
if (error) {
callback(error);
}
console.log('Finished trip with', stats.point_count, 'points');
console.log('Passed', stats.feature_count, 'features');
console.log('Travelled', stats.distance, 'meters');
console.log('It took', stats.elapsed_time, 'seconds');
callback();
});
/**
* Constructs a function that asynchronously sends the given point and then
* delays sending its callback
* @param {number} lat The latitude to send
* @param {number} lng The longitude to send
* @return {function(function)} The function that sends the point
*/
function pointSender(lat, lng) {
/**
* Sends the point, then calls the callback after a delay
* @param {function} callback Called when complete
*/
return function(callback) {
console.log('Visiting point ' + lat/COORD_FACTOR + ', ' +
lng/COORD_FACTOR);
call.write({
latitude: lat,
longitude: lng
});
_.delay(callback, _.random(500, 1500));
};
}
var point_senders = [];
for (var i = 0; i < num_points; i++) {
var rand_point = feature_list[_.random(0, feature_list.length - 1)];
point_senders[i] = pointSender(rand_point.location.latitude,
rand_point.location.longitude);
}
async.series(point_senders, function() {
call.end();
});
});
}
/**
* Run the routeChat demo. Send some chat messages, and print any chat messages
* that are sent from the server.
* @param {function} callback Called when the demo is complete
*/
function runRouteChat(callback) {
var call = client.routeChat();
call.on('data', function(note) {
console.log('Got message "' + note.message + '" at ' +
note.location.latitude + ', ' + note.location.longitude);
});
call.on('end', callback);
var notes = [{
location: {
latitude: 0,
longitude: 0
},
message: 'First message'
}, {
location: {
latitude: 0,
longitude: 1
},
message: 'Second message'
}, {
location: {
latitude: 1,
longitude: 0
},
message: 'Third message'
}, {
location: {
latitude: 0,
longitude: 0
},
message: 'Fourth message'
}];
for (var i = 0; i < notes.length; i++) {
var note = notes[i];
console.log('Sending message "' + note.message + '" at ' +
note.location.latitude + ', ' + note.location.longitude);
call.write(note);
}
call.end();
}
/**
* Run all of the demos in order
*/
function main() {
async.series([
runGetFeature,
runListFeatures,
runRecordRoute,
runRouteChat
]);
}
if (require.main === module) {
main();
}
exports.runGetFeature = runGetFeature;
exports.runListFeatures = runListFeatures;
exports.runRecordRoute = runRecordRoute;
exports.runRouteChat = runRouteChat;

@ -0,0 +1,601 @@
[{
"location": {
"latitude": 407838351,
"longitude": -746143763
},
"name": "Patriots Path, Mendham, NJ 07945, USA"
}, {
"location": {
"latitude": 408122808,
"longitude": -743999179
},
"name": "101 New Jersey 10, Whippany, NJ 07981, USA"
}, {
"location": {
"latitude": 413628156,
"longitude": -749015468
},
"name": "U.S. 6, Shohola, PA 18458, USA"
}, {
"location": {
"latitude": 419999544,
"longitude": -740371136
},
"name": "5 Conners Road, Kingston, NY 12401, USA"
}, {
"location": {
"latitude": 414008389,
"longitude": -743951297
},
"name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA"
}, {
"location": {
"latitude": 419611318,
"longitude": -746524769
},
"name": "287 Flugertown Road, Livingston Manor, NY 12758, USA"
}, {
"location": {
"latitude": 406109563,
"longitude": -742186778
},
"name": "4001 Tremley Point Road, Linden, NJ 07036, USA"
}, {
"location": {
"latitude": 416802456,
"longitude": -742370183
},
"name": "352 South Mountain Road, Wallkill, NY 12589, USA"
}, {
"location": {
"latitude": 412950425,
"longitude": -741077389
},
"name": "Bailey Turn Road, Harriman, NY 10926, USA"
}, {
"location": {
"latitude": 412144655,
"longitude": -743949739
},
"name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA"
}, {
"location": {
"latitude": 415736605,
"longitude": -742847522
},
"name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA"
}, {
"location": {
"latitude": 413843930,
"longitude": -740501726
},
"name": "162 Merrill Road, Highland Mills, NY 10930, USA"
}, {
"location": {
"latitude": 410873075,
"longitude": -744459023
},
"name": "Clinton Road, West Milford, NJ 07480, USA"
}, {
"location": {
"latitude": 412346009,
"longitude": -744026814
},
"name": "16 Old Brook Lane, Warwick, NY 10990, USA"
}, {
"location": {
"latitude": 402948455,
"longitude": -747903913
},
"name": "3 Drake Lane, Pennington, NJ 08534, USA"
}, {
"location": {
"latitude": 406337092,
"longitude": -740122226
},
"name": "6324 8th Avenue, Brooklyn, NY 11220, USA"
}, {
"location": {
"latitude": 406421967,
"longitude": -747727624
},
"name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA"
}, {
"location": {
"latitude": 416318082,
"longitude": -749677716
},
"name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA"
}, {
"location": {
"latitude": 415301720,
"longitude": -748416257
},
"name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA"
}, {
"location": {
"latitude": 402647019,
"longitude": -747071791
},
"name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA"
}, {
"location": {
"latitude": 412567807,
"longitude": -741058078
},
"name": "New York State Reference Route 987E, Southfields, NY 10975, USA"
}, {
"location": {
"latitude": 416855156,
"longitude": -744420597
},
"name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA"
}, {
"location": {
"latitude": 404663628,
"longitude": -744820157
},
"name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA"
}, {
"location": {
"latitude": 407113723,
"longitude": -749746483
},
"name": ""
}, {
"location": {
"latitude": 402133926,
"longitude": -743613249
},
"name": ""
}, {
"location": {
"latitude": 400273442,
"longitude": -741220915
},
"name": ""
}, {
"location": {
"latitude": 411236786,
"longitude": -744070769
},
"name": ""
}, {
"location": {
"latitude": 411633782,
"longitude": -746784970
},
"name": "211-225 Plains Road, Augusta, NJ 07822, USA"
}, {
"location": {
"latitude": 415830701,
"longitude": -742952812
},
"name": ""
}, {
"location": {
"latitude": 413447164,
"longitude": -748712898
},
"name": "165 Pedersen Ridge Road, Milford, PA 18337, USA"
}, {
"location": {
"latitude": 405047245,
"longitude": -749800722
},
"name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA"
}, {
"location": {
"latitude": 418858923,
"longitude": -746156790
},
"name": ""
}, {
"location": {
"latitude": 417951888,
"longitude": -748484944
},
"name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA"
}, {
"location": {
"latitude": 407033786,
"longitude": -743977337
},
"name": "26 East 3rd Street, New Providence, NJ 07974, USA"
}, {
"location": {
"latitude": 417548014,
"longitude": -740075041
},
"name": ""
}, {
"location": {
"latitude": 410395868,
"longitude": -744972325
},
"name": ""
}, {
"location": {
"latitude": 404615353,
"longitude": -745129803
},
"name": ""
}, {
"location": {
"latitude": 406589790,
"longitude": -743560121
},
"name": "611 Lawrence Avenue, Westfield, NJ 07090, USA"
}, {
"location": {
"latitude": 414653148,
"longitude": -740477477
},
"name": "18 Lannis Avenue, New Windsor, NY 12553, USA"
}, {
"location": {
"latitude": 405957808,
"longitude": -743255336
},
"name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA"
}, {
"location": {
"latitude": 411733589,
"longitude": -741648093
},
"name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA"
}, {
"location": {
"latitude": 412676291,
"longitude": -742606606
},
"name": "1270 Lakes Road, Monroe, NY 10950, USA"
}, {
"location": {
"latitude": 409224445,
"longitude": -748286738
},
"name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA"
}, {
"location": {
"latitude": 406523420,
"longitude": -742135517
},
"name": "652 Garden Street, Elizabeth, NJ 07202, USA"
}, {
"location": {
"latitude": 401827388,
"longitude": -740294537
},
"name": "349 Sea Spray Court, Neptune City, NJ 07753, USA"
}, {
"location": {
"latitude": 410564152,
"longitude": -743685054
},
"name": "13-17 Stanley Street, West Milford, NJ 07480, USA"
}, {
"location": {
"latitude": 408472324,
"longitude": -740726046
},
"name": "47 Industrial Avenue, Teterboro, NJ 07608, USA"
}, {
"location": {
"latitude": 412452168,
"longitude": -740214052
},
"name": "5 White Oak Lane, Stony Point, NY 10980, USA"
}, {
"location": {
"latitude": 409146138,
"longitude": -746188906
},
"name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA"
}, {
"location": {
"latitude": 404701380,
"longitude": -744781745
},
"name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA"
}, {
"location": {
"latitude": 409642566,
"longitude": -746017679
},
"name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA"
}, {
"location": {
"latitude": 408031728,
"longitude": -748645385
},
"name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA"
}, {
"location": {
"latitude": 413700272,
"longitude": -742135189
},
"name": "367 Prospect Road, Chester, NY 10918, USA"
}, {
"location": {
"latitude": 404310607,
"longitude": -740282632
},
"name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA"
}, {
"location": {
"latitude": 409319800,
"longitude": -746201391
},
"name": "11 Ward Street, Mount Arlington, NJ 07856, USA"
}, {
"location": {
"latitude": 406685311,
"longitude": -742108603
},
"name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA"
}, {
"location": {
"latitude": 419018117,
"longitude": -749142781
},
"name": "43 Dreher Road, Roscoe, NY 12776, USA"
}, {
"location": {
"latitude": 412856162,
"longitude": -745148837
},
"name": "Swan Street, Pine Island, NY 10969, USA"
}, {
"location": {
"latitude": 416560744,
"longitude": -746721964
},
"name": "66 Pleasantview Avenue, Monticello, NY 12701, USA"
}, {
"location": {
"latitude": 405314270,
"longitude": -749836354
},
"name": ""
}, {
"location": {
"latitude": 414219548,
"longitude": -743327440
},
"name": ""
}, {
"location": {
"latitude": 415534177,
"longitude": -742900616
},
"name": "565 Winding Hills Road, Montgomery, NY 12549, USA"
}, {
"location": {
"latitude": 406898530,
"longitude": -749127080
},
"name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA"
}, {
"location": {
"latitude": 407586880,
"longitude": -741670168
},
"name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA"
}, {
"location": {
"latitude": 400106455,
"longitude": -742870190
},
"name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA"
}, {
"location": {
"latitude": 400066188,
"longitude": -746793294
},
"name": ""
}, {
"location": {
"latitude": 418803880,
"longitude": -744102673
},
"name": "40 Mountain Road, Napanoch, NY 12458, USA"
}, {
"location": {
"latitude": 414204288,
"longitude": -747895140
},
"name": ""
}, {
"location": {
"latitude": 414777405,
"longitude": -740615601
},
"name": ""
}, {
"location": {
"latitude": 415464475,
"longitude": -747175374
},
"name": "48 North Road, Forestburgh, NY 12777, USA"
}, {
"location": {
"latitude": 404062378,
"longitude": -746376177
},
"name": ""
}, {
"location": {
"latitude": 405688272,
"longitude": -749285130
},
"name": ""
}, {
"location": {
"latitude": 400342070,
"longitude": -748788996
},
"name": ""
}, {
"location": {
"latitude": 401809022,
"longitude": -744157964
},
"name": ""
}, {
"location": {
"latitude": 404226644,
"longitude": -740517141
},
"name": "9 Thompson Avenue, Leonardo, NJ 07737, USA"
}, {
"location": {
"latitude": 410322033,
"longitude": -747871659
},
"name": ""
}, {
"location": {
"latitude": 407100674,
"longitude": -747742727
},
"name": ""
}, {
"location": {
"latitude": 418811433,
"longitude": -741718005
},
"name": "213 Bush Road, Stone Ridge, NY 12484, USA"
}, {
"location": {
"latitude": 415034302,
"longitude": -743850945
},
"name": ""
}, {
"location": {
"latitude": 411349992,
"longitude": -743694161
},
"name": ""
}, {
"location": {
"latitude": 404839914,
"longitude": -744759616
},
"name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA"
}, {
"location": {
"latitude": 414638017,
"longitude": -745957854
},
"name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA"
}, {
"location": {
"latitude": 412127800,
"longitude": -740173578
},
"name": ""
}, {
"location": {
"latitude": 401263460,
"longitude": -747964303
},
"name": ""
}, {
"location": {
"latitude": 412843391,
"longitude": -749086026
},
"name": ""
}, {
"location": {
"latitude": 418512773,
"longitude": -743067823
},
"name": ""
}, {
"location": {
"latitude": 404318328,
"longitude": -740835638
},
"name": "42-102 Main Street, Belford, NJ 07718, USA"
}, {
"location": {
"latitude": 419020746,
"longitude": -741172328
},
"name": ""
}, {
"location": {
"latitude": 404080723,
"longitude": -746119569
},
"name": ""
}, {
"location": {
"latitude": 401012643,
"longitude": -744035134
},
"name": ""
}, {
"location": {
"latitude": 404306372,
"longitude": -741079661
},
"name": ""
}, {
"location": {
"latitude": 403966326,
"longitude": -748519297
},
"name": ""
}, {
"location": {
"latitude": 405002031,
"longitude": -748407866
},
"name": ""
}, {
"location": {
"latitude": 409532885,
"longitude": -742200683
},
"name": ""
}, {
"location": {
"latitude": 416851321,
"longitude": -742674555
},
"name": ""
}, {
"location": {
"latitude": 406411633,
"longitude": -741722051
},
"name": "3387 Richmond Terrace, Staten Island, NY 10303, USA"
}, {
"location": {
"latitude": 413069058,
"longitude": -744597778
},
"name": "261 Van Sickle Road, Goshen, NY 10924, USA"
}, {
"location": {
"latitude": 418465462,
"longitude": -746859398
},
"name": ""
}, {
"location": {
"latitude": 411733222,
"longitude": -744228360
},
"name": ""
}, {
"location": {
"latitude": 410248224,
"longitude": -747127767
},
"name": "3 Hasta Way, Newton, NJ 07860, USA"
}]

@ -0,0 +1,249 @@
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
var fs = require('fs');
var parseArgs = require('minimist');
var path = require('path');
var _ = require('underscore');
var grpc = require('grpc');
var examples = grpc.load(__dirname + '/route_guide.proto').examples;
var Server = grpc.buildServer([examples.RouteGuide.service]);
var COORD_FACTOR = 1e7;
/**
* For simplicity, a point is a record type that looks like
* {latitude: number, longitude: number}, and a feature is a record type that
* looks like {name: string, location: point}. feature objects with name===''
* are points with no feature.
*/
/**
* List of feature objects at points that have been requested so far.
*/
var feature_list = [];
/**
* Get a feature object at the given point, or creates one if it does not exist.
* @param {point} point The point to check
* @return {feature} The feature object at the point. Note that an empty name
* indicates no feature
*/
function checkFeature(point) {
var feature;
// Check if there is already a feature object for the given point
for (var i = 0; i < feature_list.length; i++) {
feature = feature_list[i];
if (feature.location.latitude === point.latitude &&
feature.location.longitude === point.longitude) {
return feature;
}
}
var name = '';
feature = {
name: name,
location: point
};
return feature;
}
/**
* getFeature request handler. Gets a request with a point, and responds with a
* feature object indicating whether there is a feature at that point.
* @param {EventEmitter} call Call object for the handler to process
* @param {function(Error, feature)} callback Response callback
*/
function getFeature(call, callback) {
callback(null, checkFeature(call.request));
}
/**
* listFeatures request handler. Gets a request with two points, and responds
* with a stream of all features in the bounding box defined by those points.
* @param {Writable} call Writable stream for responses with an additional
* request property for the request value.
*/
function listFeatures(call) {
var lo = call.request.lo;
var hi = call.request.hi;
var left = _.min([lo.longitude, hi.longitude]);
var right = _.max([lo.longitude, hi.longitude]);
var top = _.max([lo.latitude, hi.latitude]);
var bottom = _.min([lo.latitude, hi.latitude]);
// For each feature, check if it is in the given bounding box
_.each(feature_list, function(feature) {
if (feature.name === '') {
return;
}
if (feature.location.longitude >= left &&
feature.location.longitude <= right &&
feature.location.latitude >= bottom &&
feature.location.latitude <= top) {
call.write(feature);
}
});
call.end();
}
/**
* Calculate the distance between two points using the "haversine" formula.
* This code was taken from http://www.movable-type.co.uk/scripts/latlong.html.
* @param start The starting point
* @param end The end point
* @return The distance between the points in meters
*/
function getDistance(start, end) {
function toRadians(num) {
return num * Math.PI / 180;
}
var lat1 = start.latitude / COORD_FACTOR;
var lat2 = end.latitude / COORD_FACTOR;
var lon1 = start.longitude / COORD_FACTOR;
var lon2 = end.longitude / COORD_FACTOR;
var R = 6371000; // metres
var φ1 = toRadians(lat1);
var φ2 = toRadians(lat2);
var Δφ = toRadians(lat2-lat1);
var Δλ = toRadians(lon2-lon1);
var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ/2) * Math.sin(Δλ/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return R * c;
}
/**
* recordRoute handler. Gets a stream of points, and responds with statistics
* about the "trip": number of points, number of known features visited, total
* distance traveled, and total time spent.
* @param {Readable} call The request point stream.
* @param {function(Error, routeSummary)} callback The callback to pass the
* response to
*/
function recordRoute(call, callback) {
var point_count = 0;
var feature_count = 0;
var distance = 0;
var previous = null;
// Start a timer
var start_time = process.hrtime();
call.on('data', function(point) {
point_count += 1;
if (checkFeature(point).name !== '') {
feature_count += 1;
}
/* For each point after the first, add the incremental distance from the
* previous point to the total distance value */
if (previous != null) {
distance += getDistance(previous, point);
}
previous = point;
});
call.on('end', function() {
callback(null, {
point_count: point_count,
feature_count: feature_count,
// Cast the distance to an integer
distance: distance|0,
// End the timer
elapsed_time: process.hrtime(start_time)[0]
});
});
}
var route_notes = {};
/**
* Turn the point into a dictionary key.
* @param {point} point The point to use
* @return {string} The key for an object
*/
function pointKey(point) {
return point.latitude + ' ' + point.longitude;
}
/**
* routeChat handler. Receives a stream of message/location pairs, and responds
* with a stream of all previous messages at each of those locations.
* @param {Duplex} call The stream for incoming and outgoing messages
*/
function routeChat(call) {
call.on('data', function(note) {
var key = pointKey(note.location);
/* For each note sent, respond with all previous notes that correspond to
* the same point */
if (route_notes.hasOwnProperty(key)) {
_.each(route_notes[key], function(note) {
call.write(note);
});
} else {
route_notes[key] = [];
}
// Then add the new note to the list
route_notes[key].push(JSON.parse(JSON.stringify(note)));
});
call.on('end', function() {
call.end();
});
}
/**
* Get a new server with the handler functions in this file bound to the methods
* it serves.
* @return {Server} The new server object
*/
function getServer() {
return new Server({
'examples.RouteGuide' : {
getFeature: getFeature,
listFeatures: listFeatures,
recordRoute: recordRoute,
routeChat: routeChat
}
});
}
if (require.main === module) {
// If this is run as a script, start a server on an unused port
var routeServer = getServer();
routeServer.bind('0.0.0.0:50051');
var argv = parseArgs(process.argv, {
string: 'db_path'
});
fs.readFile(path.resolve(argv.db_path), function(err, data) {
if (err) throw err;
feature_list = JSON.parse(data);
routeServer.listen();
});
}
exports.getServer = getServer;

@ -0,0 +1,8 @@
# Example protos
## Contents
- [helloworld.proto]
- The simple example used in the overview.
- [route_guide.proto]
- An example service described in detail in the tutorial.

@ -0,0 +1,53 @@
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
option java_package = "ex.grpc";
package hellostreamingworld;
// The greeting service definition.
service MultiGreeter {
// Sends multiple greetings
rpc sayHello (HelloRequest) returns (stream HelloReply) {}
}
// The request message containing the user's name and how many greetings
// they want.
message HelloRequest {
string name = 1;
string num_greetings = 2;
}
// A response message containing a greeting
message HelloReply {
string message = 1;
}

@ -0,0 +1,50 @@
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
option java_package = "ex.grpc";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}

@ -0,0 +1,120 @@
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
option java_package = "ex.grpc";
package examples;
// Interface exported by the server.
service RouteGuide {
// A simple RPC.
//
// Obtains the feature at a given position.
rpc GetFeature(Point) returns (Feature) {}
// A server-to-client streaming RPC.
//
// Obtains the Features available within the given Rectangle. Results are
// streamed rather than returned at once (e.g. in a response message with a
// repeated field), as the rectangle may cover a large area and contain a
// huge number of features.
rpc ListFeatures(Rectangle) returns (stream Feature) {}
// A client-to-server streaming RPC.
//
// Accepts a stream of Points on a route being traversed, returning a
// RouteSummary when traversal is completed.
rpc RecordRoute(stream Point) returns (RouteSummary) {}
// A Bidirectional streaming RPC.
//
// Accepts a stream of RouteNotes sent while a route is being traversed,
// while receiving other RouteNotes (e.g. from other users).
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}
// Points are represented as latitude-longitude pairs in the E7 representation
// (degrees multiplied by 10**7 and rounded to the nearest integer).
// Latitudes should be in the range +/- 90 degrees and longitude should be in
// the range +/- 180 degrees (inclusive).
message Point {
int32 latitude = 1;
int32 longitude = 2;
}
// A latitude-longitude rectangle, represented as two diagonally opposite
// points "lo" and "hi".
message Rectangle {
// One corner of the rectangle.
Point lo = 1;
// The other corner of the rectangle.
Point hi = 2;
}
// A feature names something at a given point.
//
// If a feature could not be named, the name is empty.
message Feature {
// The name of the feature.
string name = 1;
// The point where the feature is detected.
Point location = 2;
}
// A RouteNote is a message sent while at a given point.
message RouteNote {
// The location from which the message is sent.
Point location = 1;
// The message to be sent.
string message = 2;
}
// A RouteSummary is received in response to a RecordRoute rpc.
//
// It contains the number of individual points received, the number of
// detected features, and the total distance covered as the cumulative sum of
// the distance between each point.
message RouteSummary {
// The number of points received.
int32 point_count = 1;
// The number of known features passed while traversing the route.
int32 feature_count = 2;
// The distance covered in metres.
int32 distance = 3;
// The duration of the traversal in seconds.
int32 elapsed_time = 4;
}

15
ruby/.gitignore vendored

@ -0,0 +1,15 @@
/.bundle/
/.yardoc
/Gemfile.lock
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
*.bundle
*.so
*.o
*.a
mkmf.log
vendor

@ -0,0 +1,15 @@
# -*- ruby -*-
# encoding: utf-8
source 'https://rubygems.org/'
# Update this to reflect the local installation of gRPC.
gem 'grpc', path: '/usr/local/google/repos/grpc/src/ruby'
# TODO: fix this if/when the gRPC repo structure changes.
#
# At the moment it's not possible to use grpc Ruby via git/github reference
#
# git 'git@github.com:grpc/grpc.git' do
# gem 'grpc'
# end

@ -0,0 +1,35 @@
gRPC in 3 minutes (Ruby)
========================
PREREQUISITES
-------------
This requires Ruby 2.1, as the gRPC API surface uses keyword args.
INSTALL
-------
- Clone this repository.
- Follow the instructions in [INSTALL](https://github.com/grpc/grpc/blob/master/INSTALL) to install the gRPC C core.
- *Temporary* Install the full gRPC distribution from source on your local machine and update path: in [Gemfile] to refer src/ruby within it.
- this is necessary until the gRPC ruby gem is published
- Use bundler to install
```sh
$ # from this directory
$ gem install bundler && bundle install
```
Try it!
-------
- Run the server
```sh
$ # from this directory
$ bundle exec ./greeter_server.rb &
```
- Run the client
```sh
$ # from this directory
$ bundle exec ./greeter_client.rb
```

@ -0,0 +1,23 @@
# -*- ruby -*-
# encoding: utf-8
Gem::Specification.new do |s|
s.name = 'grpc-greeter'
s.version = '0.1.0'
s.authors = ['gRPC Authors']
s.email = 'temiola@google.com'
s.homepage = 'https://github.com/grpc/grpc-common'
s.summary = 'gRPC Ruby overview sample'
s.description = 'Simple demo of using gRPC from Ruby'
s.files = `git ls-files -- ruby/*`.split("\n")
s.executables = `git ls-files -- ruby/greeter*.rb`.split("\n").map do |f|
File.basename(f)
end
s.require_paths = ['lib']
s.platform = Gem::Platform::RUBY
s.add_dependency 'grpc', '~> 0.0.1'
s.add_development_dependency 'bundler', '~> 1.7'
end

@ -0,0 +1,50 @@
#!/usr/bin/env ruby
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Sample app that connects to a Greeter service.
#
# Usage: $ path/to/greeter_client.rb
this_dir = File.expand_path(File.dirname(__FILE__))
lib_dir = File.join(this_dir, 'lib')
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc'
require 'helloworld_services'
def main
stub = Helloworld::Greeter::Stub.new('localhost:50051')
user = ARGV.size > 0 ? ARGV[0] : 'world'
message = stub.say_hello(Helloworld::HelloRequest.new(name: user)).message
p "Greeting: #{message}"
end
main

@ -0,0 +1,60 @@
#!/usr/bin/env ruby
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Sample gRPC server that implements the Greeter::Helloworld service.
#
# Usage: $ path/to/greeter_server.rb
this_dir = File.expand_path(File.dirname(__FILE__))
lib_dir = File.join(this_dir, 'lib')
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc'
require 'helloworld_services'
# GreeterServer is simple server that implements the Helloworld Greeter server.
class GreeterServer < Helloworld::Greeter::Service
# say_hello implements the SayHello rpc method.
def say_hello(hello_req, _unused_call)
Helloworld::HelloReply.new(message: "Hello #{hello_req.name}")
end
end
# main starts an RpcServer that receives requests to GreeterServer at the sample
# server port.
def main
s = GRPC::RpcServer.new
s.add_http2_port('0.0.0.0:50051')
s.handle(GreeterServer)
s.run
end
main

@ -0,0 +1,18 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: helloworld.proto
require 'google/protobuf'
Google::Protobuf::DescriptorPool.generated_pool.build do
add_message "helloworld.HelloRequest" do
optional :name, :string, 1
end
add_message "helloworld.HelloReply" do
optional :message, :string, 1
end
end
module Helloworld
HelloRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("helloworld.HelloRequest").msgclass
HelloReply = Google::Protobuf::DescriptorPool.generated_pool.lookup("helloworld.HelloReply").msgclass
end

@ -0,0 +1,24 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# Source: helloworld.proto for package 'helloworld'
require 'grpc'
require 'helloworld'
module Helloworld
module Greeter
# TODO: add proto service documentation here
class Service
include GRPC::GenericService
self.marshal_class_method = :encode
self.unmarshal_class_method = :decode
self.service_name = 'helloworld.Greeter'
rpc :SayHello, HelloRequest, HelloReply
end
Stub = Service.rpc_stub_class
end
end

@ -1,22 +0,0 @@
syntax = "proto3";
option java_package = "ex.grpc";
package helloworld;
// The request message containing the user's name.
message HelloRequest {
optional string name = 1;
}
// The response message containing the greetings
message HelloReply {
optional string message = 1;
}
// The greeting service definition.
service Greetings {
// Sends a greeting
rpc hello (HelloRequest) returns (HelloReply) {
}
}
Loading…
Cancel
Save