C# route guide
This commit is contained in:
parent
0b634e3d87
commit
e003f010cd
|
|
@ -0,0 +1,5 @@
|
|||
bin/
|
||||
obj/
|
||||
packages/
|
||||
*.suo
|
||||
*.userprefs
|
||||
|
|
@ -0,0 +1,392 @@
|
|||
#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 only uses the proto2 version of the protocol buffers language, as proto3 support for C# is not ready yet (see [protobuf C# README](https://github.com/google/protobuf/tree/master/csharp#proto2--proto3)).
|
||||
|
||||
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.
|
||||
|
||||
## Example code and setup
|
||||
|
||||
The example code for our tutorial is in [grpc/grpc-common/csharp/route_guide](https://github.com/grpc/grpc-common/tree/master/csharp/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
|
||||
```
|
||||
|
||||
All the files for this tutorial are in the directory `grpc-common/csharp/route_guide`.
|
||||
Open the solution `grpc-common/csharp/route_guide/RouteGuide.sln` from Visual Studio (or Monodevelop on Linux).
|
||||
|
||||
You also should have the relevant tools installed to generate the server and client interface code.
|
||||
|
||||
**TODO: more on how to install protoc**
|
||||
|
||||
## 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/csharp/route_guide/RouteGuide/protos/route_guide.proto`](https://github.com/grpc/grpc-common/blob/master/sharp/route_guide/RouteGuide/protos/route_guide.proto).
|
||||
|
||||
To define a service, you specify a named `service` in your .proto file:
|
||||
|
||||
```protobuf
|
||||
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.
|
||||
```protobuf
|
||||
// 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.
|
||||
```protobuf
|
||||
// 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.
|
||||
```protobuf
|
||||
// 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.
|
||||
```protobuf
|
||||
// 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:
|
||||
```protobuf
|
||||
// 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.
|
||||
|
||||
If you want to run this yourself, make sure you've installed protoc and followed the gRPC C# plugin [installation instructions](https://github.com/grpc/grpc/blob/master/INSTALL) first.
|
||||
|
||||
**TODO: more on how to install protoc and grpc_csharp_plugin**
|
||||
|
||||
Once that's done, the following command can be used to generate the C# code.
|
||||
|
||||
```shell
|
||||
$ protoc -I RouteGuide/protos --csharp_out=RouteGuide --grpc_out=RouteGuide --plugin=protoc-gen-grpc=`which grpc_csharp_plugin` RouteGuide/protos/route_guide.proto
|
||||
```
|
||||
|
||||
**TODO: command for windows**
|
||||
|
||||
Running this command regenerates the following files in the RouteGuide directory:
|
||||
- `RouteGuide/RouteGuide.cs` defines a namespace `examples`
|
||||
- This contains all the protocol buffer code to populate, serialize, and retrieve our request and response message types
|
||||
- `RouteGuide/RouteGuideGrpc.cs`, provides stub and service classes
|
||||
- an interface `RouteGuide.IRouteGuide` to inherit from when defining RouteGuide service implementations
|
||||
- a class `RouteGuide.RouteGuideClient` that can be used to access remote RouteGuide instances
|
||||
|
||||
|
||||
<a name="server"></a>
|
||||
## Creating the server
|
||||
|
||||
First let's look at how we create a `RouteGuide` server. If you're only interested in creating gRPC clients, you can skip this section and go straight to [Creating the client](#client) (though you might find it interesting anyway!).
|
||||
|
||||
There are two parts to making our `RouteGuide` service do its job:
|
||||
- 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.
|
||||
|
||||
You can find our example `RouteGuide` server in [grpc-common/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs](https://github.com/grpc/grpc-common/blob/master/csharp/route_guide/RouteGuideServer/RouteGuideServerImpl.cs). Let's take a closer look at how it works.
|
||||
|
||||
### Implementing RouteGuide
|
||||
|
||||
As you can see, our server has a `RouteGuideImpl` class that implements the generated `RouteGuide.IRouteGuide`:
|
||||
|
||||
```csharp
|
||||
// RouteGuideImpl provides an implementation of the RouteGuide service.
|
||||
public class RouteGuideImpl : RouteGuide.IRouteGuide
|
||||
```
|
||||
|
||||
`RouteGuideImpl` implements all our service methods. Let's look at the simplest type first, `GetFeature`, which just gets a `Point` from the client and returns the corresponding feature information from its database in a `Feature`.
|
||||
|
||||
```csharp
|
||||
public Task<Feature> GetFeature(Grpc.Core.ServerCallContext context, Point request)
|
||||
{
|
||||
return Task.FromResult(CheckFeature(request));
|
||||
}
|
||||
```
|
||||
|
||||
The method is passed a context for the RPC (which is empty in the alpha release), the client's `Point` protocol buffer request, and returns a `Feature` protocol buffer. In the method we create the `Feature` with the appropriate information, and then return it. To allow asynchronous
|
||||
implementation, the method returns `Task<Feature>` rather than just `Feature`. You are free to perform your computations synchronously and return
|
||||
the result once you've finished, just as we do in the example.
|
||||
|
||||
Now let's look at something a bit more complicated - a streaming RPC. `ListFeatures` is a server-side streaming RPC, so we need to send back multiple `Feature` protocol buffers to our client.
|
||||
|
||||
```csharp
|
||||
// in RouteGuideImpl
|
||||
public async Task ListFeatures(Grpc.Core.ServerCallContext context, Rectangle request,
|
||||
Grpc.Core.IServerStreamWriter<Feature> responseStream)
|
||||
{
|
||||
int left = Math.Min(request.Lo.Longitude, request.Hi.Longitude);
|
||||
int right = Math.Max(request.Lo.Longitude, request.Hi.Longitude);
|
||||
int top = Math.Max(request.Lo.Latitude, request.Hi.Latitude);
|
||||
int bottom = Math.Min(request.Lo.Latitude, request.Hi.Latitude);
|
||||
|
||||
foreach (var feature in features)
|
||||
{
|
||||
if (!RouteGuideUtil.Exists(feature))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int lat = feature.Location.Latitude;
|
||||
int lon = feature.Location.Longitude;
|
||||
if (lon >= left && lon <= right && lat >= bottom && lat <= top)
|
||||
{
|
||||
await responseStream.WriteAsync(feature);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
As you can see, here the request object is a `Rectangle` in which our client wants to find `Feature`s, but instead of returning a simple response we need to write responses to an asynchronous stream `IServerStreamWriter` using async method `WriteAsync`.
|
||||
|
||||
Similarly, the client-side streaming method `RecordRoute` uses an [IAsyncEnumerator](https://github.com/Reactive-Extensions/Rx.NET/blob/master/Ix.NET/Source/System.Interactive.Async/IAsyncEnumerator.cs), to read the stream of requests using async method `MoveNext` and property `Current`.
|
||||
|
||||
```csharp
|
||||
public async Task<RouteSummary> RecordRoute(Grpc.Core.ServerCallContext context,
|
||||
Grpc.Core.IAsyncStreamReader<Point> requestStream)
|
||||
{
|
||||
int pointCount = 0;
|
||||
int featureCount = 0;
|
||||
int distance = 0;
|
||||
Point previous = null;
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
while (await requestStream.MoveNext())
|
||||
{
|
||||
var point = requestStream.Current;
|
||||
pointCount++;
|
||||
if (RouteGuideUtil.Exists(CheckFeature(point)))
|
||||
{
|
||||
featureCount++;
|
||||
}
|
||||
if (previous != null)
|
||||
{
|
||||
distance += (int) CalcDistance(previous, point);
|
||||
}
|
||||
previous = point;
|
||||
}
|
||||
|
||||
stopwatch.Stop();
|
||||
return RouteSummary.CreateBuilder().SetPointCount(pointCount)
|
||||
.SetFeatureCount(featureCount).SetDistance(distance)
|
||||
.SetElapsedTime((int) (stopwatch.ElapsedMilliseconds / 1000)).Build();
|
||||
}
|
||||
```
|
||||
Finally, let's look at our bidirectional streaming RPC `RouteChat`.
|
||||
|
||||
```csharp
|
||||
public async Task RouteChat(Grpc.Core.ServerCallContext context,
|
||||
Grpc.Core.IAsyncStreamReader<RouteNote> requestStream, Grpc.Core.IServerStreamWriter<RouteNote> responseStream)
|
||||
{
|
||||
while (await requestStream.MoveNext())
|
||||
{
|
||||
var note = requestStream.Current;
|
||||
List<RouteNote> notes = GetOrCreateNotes(note.Location);
|
||||
|
||||
List<RouteNote> prevNotes;
|
||||
lock (notes)
|
||||
{
|
||||
prevNotes = new List<RouteNote>(notes);
|
||||
}
|
||||
|
||||
foreach (var prevNote in prevNotes)
|
||||
{
|
||||
await responseStream.WriteAsync(prevNote);
|
||||
}
|
||||
|
||||
lock (notes)
|
||||
{
|
||||
notes.Add(note);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here the method receives both `requestStream` and `responseStream` as an argument. Reading the requests is done in a same way as in the `RecordRoute` example. Writing the responses is done the same way as in the `ListFeatures` example.
|
||||
|
||||
### Starting the server
|
||||
|
||||
Once we've implemented all our methods, we also need to start up a gRPC server so that clients can actually use our service. The following snippet shows how we do this for our `RouteGuide` service:
|
||||
|
||||
```csharp
|
||||
var features = RouteGuideUtil.ParseFeatures(RouteGuideUtil.DefaultFeaturesFile);
|
||||
GrpcEnvironment.Initialize();
|
||||
|
||||
Server server = new Server();
|
||||
server.AddServiceDefinition(RouteGuide.BindService(new RouteGuideImpl(features)));
|
||||
int port = server.AddListeningPort("localhost", 50052);
|
||||
server.Start();
|
||||
|
||||
Console.WriteLine("RouteGuide server listening on port " + port);
|
||||
Console.WriteLine("Press any key to stop the server...");
|
||||
Console.ReadKey();
|
||||
|
||||
server.ShutdownAsync().Wait();
|
||||
GrpcEnvironment.Shutdown();
|
||||
```
|
||||
As you can see, we build and start our server using `Grpc.Core.Server` class. To do this, we:
|
||||
|
||||
1. Create an instance of `Grpc.Core.Server`.
|
||||
1. Create an instance of our service implementation class `RouteGuideImpl`.
|
||||
3. Register our service implementation with the server using method `AddServiceDefinition` and the generated method `RouteGuide.BindService`.
|
||||
2. Specify the address and port we want to use to listen for client requests using the `AddListeningPort` method.
|
||||
4. Call `Start` on the server instance to start an RPC server for our service.
|
||||
|
||||
<a name="client"></a>
|
||||
## Creating the client
|
||||
|
||||
In this section, we'll look at creating a C# client for our `RouteGuide` service. You can see our complete example client code in [grpc-common/csharp/route_guide/RouteGuideClient/Program.cs](https://github.com/grpc/grpc-common/blob/master/csharp/route_guide/RouteGuideClient/Program.cs).
|
||||
|
||||
### Creating a stub
|
||||
|
||||
To call service methods, we first need to create a *stub*.
|
||||
|
||||
First, we need to create a gRPC client channel that will connect to gRPC server. Then, we use the `RouteGuide.NewStub` method of the `RouteGuide` class generated from our .proto.
|
||||
|
||||
```csharp
|
||||
GrpcEnvironment.Initialize();
|
||||
|
||||
using (Channel channel = new Channel("127.0.0.1:50052"))
|
||||
{
|
||||
var client = RouteGuide.NewStub(channel);
|
||||
|
||||
// YOUR CODE GOES HERE
|
||||
}
|
||||
|
||||
GrpcEnvironment.Shutdown();
|
||||
```
|
||||
|
||||
### Calling service methods
|
||||
|
||||
Now let's look at how we call our service methods. gRPC C# provides asynchronous versions of each of the supported method types. For convenience,
|
||||
gRPC C# also provides a synchronous method stub, but only for simple (single request/single response) RPCs.
|
||||
|
||||
#### Simple RPC
|
||||
|
||||
Calling the simple RPC `GetFeature` in a synchronous way is nearly as straightforward as calling a local method.
|
||||
|
||||
```csharp
|
||||
Point request = Point.CreateBuilder().SetLatitude(409146138).SetLongitude(-746188906).Build();
|
||||
Feature feature = client.GetFeature(request);
|
||||
```
|
||||
|
||||
As you can see, we create and populate a request protocol buffer object (in our case `Point`), and call the desired method on the client object, passing it the request. If the RPC finishes with success, the response protocol buffer (in our case `Feature`) will be returned. Otherwise, an exception of type `RpcException` will be thrown, indicating the status code of the problem.
|
||||
|
||||
Alternatively, if you are in async context, you can call an asynchronous version of the method (and use `await` keyword to await the result):
|
||||
```csharp
|
||||
Point request = Point.CreateBuilder().SetLatitude(409146138).SetLongitude(-746188906).Build();
|
||||
Feature feature = await client.GetFeatureAsync(request);
|
||||
```
|
||||
|
||||
#### Streaming RPCs
|
||||
|
||||
Now let's look at our streaming methods. If you've already read [Creating the server](#server) some of this may look very familiar - streaming RPCs are implemented in a similar way on both sides. The difference with respect to simple call is that the client methods return an instance of a call object, that provides access to request/response streams and/or asynchronous result (depending on the streaming type you are using).
|
||||
|
||||
Here's where we call the server-side streaming method `ListFeatures`, which has property `ReponseStream` of type `IAsyncEnumerator<Feature>`
|
||||
|
||||
```csharp
|
||||
using (var call = client.ListFeatures(request))
|
||||
{
|
||||
while (await call.ResponseStream.MoveNext())
|
||||
{
|
||||
Feature feature = call.ResponseStream.Current;
|
||||
Console.WriteLine("Received " + feature.ToString());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The client-side streaming method `RecordRoute` is similar, except we use the property `RequestStream` to write the requests one by one using `WriteAsync` and eventually signal that no more request will be send using `CompleteAsync`. The method result can be obtained through the property
|
||||
`Result`.
|
||||
```csharp
|
||||
using (var call = client.RecordRoute())
|
||||
{
|
||||
foreach (var point in points)
|
||||
{
|
||||
await call.RequestStream.WriteAsync(point);
|
||||
}
|
||||
await call.RequestStream.CompleteAsync();
|
||||
|
||||
RouteSummary summary = await call.Result;
|
||||
}
|
||||
```
|
||||
|
||||
Finally, let's look at our bidirectional streaming RPC `RouteChat`. In this case, we write the request to `RequestStream` and receive the responses from `ResponseStream`. As you can see from the example, the streams are independent of each other.
|
||||
|
||||
```csharp
|
||||
using (var call = client.RouteChat())
|
||||
{
|
||||
var responseReaderTask = Task.Run(async () =>
|
||||
{
|
||||
while (await call.ResponseStream.MoveNext())
|
||||
{
|
||||
var note = call.ResponseStream.Current;
|
||||
Console.WriteLine("Received " + note);
|
||||
}
|
||||
});
|
||||
|
||||
foreach (RouteNote request in requests)
|
||||
{
|
||||
await call.RequestStream.WriteAsync(request);
|
||||
}
|
||||
await call.RequestStream.CompleteAsync();
|
||||
await responseReaderTask;
|
||||
}
|
||||
```
|
||||
|
||||
## Try it out!
|
||||
|
||||
Build client and server:
|
||||
|
||||
Open the solution `grpc-common/csharp/route_guide/RouteGuide.sln` from Visual Studio (or Monodevelop on Linux) and hit "Build".
|
||||
|
||||
Run the server, which will listen on port 50052:
|
||||
```
|
||||
> cd RouteGuideServer/bin/Debug
|
||||
> RouteGuideServer.exe
|
||||
```
|
||||
|
||||
Run the client (in a different terminal):
|
||||
```
|
||||
> cd RouteGuideClient/bin/Debug
|
||||
> RouteGuideClient.exe
|
||||
```
|
||||
|
||||
You can also run the server and client directly from Visual Studio.
|
||||
|
||||
On Linux or Mac, use `mono RouteGuideServer.exe` and `mono RouteGuideClient.exe` to run the server and client.
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RouteGuide", "RouteGuide\RouteGuide.csproj", "{49954D9C-5F17-4662-96B2-73BE833DD81A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RouteGuideClient", "RouteGuideClient\RouteGuideClient.csproj", "{D47BE663-4DE3-4206-B7A8-EA3FA066DADC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RouteGuideServer", "RouteGuideServer\RouteGuideServer.csproj", "{4B7C7794-BE24-4477-ACE7-18259EB73D27}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{49954D9C-5F17-4662-96B2-73BE833DD81A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{49954D9C-5F17-4662-96B2-73BE833DD81A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{49954D9C-5F17-4662-96B2-73BE833DD81A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{49954D9C-5F17-4662-96B2-73BE833DD81A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D47BE663-4DE3-4206-B7A8-EA3FA066DADC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D47BE663-4DE3-4206-B7A8-EA3FA066DADC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D47BE663-4DE3-4206-B7A8-EA3FA066DADC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D47BE663-4DE3-4206-B7A8-EA3FA066DADC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4B7C7794-BE24-4477-ACE7-18259EB73D27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4B7C7794-BE24-4477-ACE7-18259EB73D27}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4B7C7794-BE24-4477-ACE7-18259EB73D27}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4B7C7794-BE24-4477-ACE7-18259EB73D27}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("RouteGuide")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("RouteGuide")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("ef6b85bc-ac27-46de-8714-a658236cc6fb")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,99 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.props" Condition="Exists('..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.props')" />
|
||||
<Import Project="..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props" Condition="Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props')" />
|
||||
<Import Project="..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props" Condition="Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{49954D9C-5F17-4662-96B2-73BE833DD81A}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>RouteGuide</RootNamespace>
|
||||
<AssemblyName>RouteGuide</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<NuGetPackageImportStamp>247686dc</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Google.ProtocolBuffers">
|
||||
<HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Google.ProtocolBuffers.Serialization">
|
||||
<HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.Serialization.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Grpc.Core">
|
||||
<HintPath>..\packages\Grpc.Core.0.5.0\lib\net45\Grpc.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.7.0.1-beta2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Collections.Immutable">
|
||||
<HintPath>..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Interactive.Async">
|
||||
<HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="RouteGuide.cs" />
|
||||
<Compile Include="RouteGuideGrpc.cs" />
|
||||
<Compile Include="RouteGuideUtil.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="protos\route_guide.proto" />
|
||||
<None Include="route_guide_db.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props'))" />
|
||||
<Error Condition="!Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props'))" />
|
||||
<Error Condition="!Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.props'))" />
|
||||
<Error Condition="!Exists('..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets')" />
|
||||
<Import Project="..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets')" />
|
||||
<Import Project="..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.targets" Condition="Exists('..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.targets')" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: route_guide.proto
|
||||
#region Designer generated code
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Grpc.Core;
|
||||
|
||||
namespace examples {
|
||||
public static class RouteGuide
|
||||
{
|
||||
static readonly string __ServiceName = "examples.RouteGuide";
|
||||
|
||||
static readonly Marshaller<global::examples.Point> __Marshaller_Point = Marshallers.Create((arg) => arg.ToByteArray(), global::examples.Point.ParseFrom);
|
||||
static readonly Marshaller<global::examples.Feature> __Marshaller_Feature = Marshallers.Create((arg) => arg.ToByteArray(), global::examples.Feature.ParseFrom);
|
||||
static readonly Marshaller<global::examples.Rectangle> __Marshaller_Rectangle = Marshallers.Create((arg) => arg.ToByteArray(), global::examples.Rectangle.ParseFrom);
|
||||
static readonly Marshaller<global::examples.RouteSummary> __Marshaller_RouteSummary = Marshallers.Create((arg) => arg.ToByteArray(), global::examples.RouteSummary.ParseFrom);
|
||||
static readonly Marshaller<global::examples.RouteNote> __Marshaller_RouteNote = Marshallers.Create((arg) => arg.ToByteArray(), global::examples.RouteNote.ParseFrom);
|
||||
|
||||
static readonly Method<global::examples.Point, global::examples.Feature> __Method_GetFeature = new Method<global::examples.Point, global::examples.Feature>(
|
||||
MethodType.Unary,
|
||||
"GetFeature",
|
||||
__Marshaller_Point,
|
||||
__Marshaller_Feature);
|
||||
|
||||
static readonly Method<global::examples.Rectangle, global::examples.Feature> __Method_ListFeatures = new Method<global::examples.Rectangle, global::examples.Feature>(
|
||||
MethodType.ServerStreaming,
|
||||
"ListFeatures",
|
||||
__Marshaller_Rectangle,
|
||||
__Marshaller_Feature);
|
||||
|
||||
static readonly Method<global::examples.Point, global::examples.RouteSummary> __Method_RecordRoute = new Method<global::examples.Point, global::examples.RouteSummary>(
|
||||
MethodType.ClientStreaming,
|
||||
"RecordRoute",
|
||||
__Marshaller_Point,
|
||||
__Marshaller_RouteSummary);
|
||||
|
||||
static readonly Method<global::examples.RouteNote, global::examples.RouteNote> __Method_RouteChat = new Method<global::examples.RouteNote, global::examples.RouteNote>(
|
||||
MethodType.DuplexStreaming,
|
||||
"RouteChat",
|
||||
__Marshaller_RouteNote,
|
||||
__Marshaller_RouteNote);
|
||||
|
||||
// client-side stub interface
|
||||
public interface IRouteGuideClient
|
||||
{
|
||||
global::examples.Feature GetFeature(global::examples.Point request, CancellationToken token = default(CancellationToken));
|
||||
Task<global::examples.Feature> GetFeatureAsync(global::examples.Point request, CancellationToken token = default(CancellationToken));
|
||||
AsyncServerStreamingCall<global::examples.Feature> ListFeatures(global::examples.Rectangle request, CancellationToken token = default(CancellationToken));
|
||||
AsyncClientStreamingCall<global::examples.Point, global::examples.RouteSummary> RecordRoute(CancellationToken token = default(CancellationToken));
|
||||
AsyncDuplexStreamingCall<global::examples.RouteNote, global::examples.RouteNote> RouteChat(CancellationToken token = default(CancellationToken));
|
||||
}
|
||||
|
||||
// server-side interface
|
||||
public interface IRouteGuide
|
||||
{
|
||||
Task<global::examples.Feature> GetFeature(ServerCallContext context, global::examples.Point request);
|
||||
Task ListFeatures(ServerCallContext context, global::examples.Rectangle request, IServerStreamWriter<global::examples.Feature> responseStream);
|
||||
Task<global::examples.RouteSummary> RecordRoute(ServerCallContext context, IAsyncStreamReader<global::examples.Point> requestStream);
|
||||
Task RouteChat(ServerCallContext context, IAsyncStreamReader<global::examples.RouteNote> requestStream, IServerStreamWriter<global::examples.RouteNote> responseStream);
|
||||
}
|
||||
|
||||
// client stub
|
||||
public class RouteGuideClient : AbstractStub<RouteGuideClient, StubConfiguration>, IRouteGuideClient
|
||||
{
|
||||
public RouteGuideClient(Channel channel) : this(channel, StubConfiguration.Default)
|
||||
{
|
||||
}
|
||||
public RouteGuideClient(Channel channel, StubConfiguration config) : base(channel, config)
|
||||
{
|
||||
}
|
||||
public global::examples.Feature GetFeature(global::examples.Point request, CancellationToken token = default(CancellationToken))
|
||||
{
|
||||
var call = CreateCall(__ServiceName, __Method_GetFeature);
|
||||
return Calls.BlockingUnaryCall(call, request, token);
|
||||
}
|
||||
public Task<global::examples.Feature> GetFeatureAsync(global::examples.Point request, CancellationToken token = default(CancellationToken))
|
||||
{
|
||||
var call = CreateCall(__ServiceName, __Method_GetFeature);
|
||||
return Calls.AsyncUnaryCall(call, request, token);
|
||||
}
|
||||
public AsyncServerStreamingCall<global::examples.Feature> ListFeatures(global::examples.Rectangle request, CancellationToken token = default(CancellationToken))
|
||||
{
|
||||
var call = CreateCall(__ServiceName, __Method_ListFeatures);
|
||||
return Calls.AsyncServerStreamingCall(call, request, token);
|
||||
}
|
||||
public AsyncClientStreamingCall<global::examples.Point, global::examples.RouteSummary> RecordRoute(CancellationToken token = default(CancellationToken))
|
||||
{
|
||||
var call = CreateCall(__ServiceName, __Method_RecordRoute);
|
||||
return Calls.AsyncClientStreamingCall(call, token);
|
||||
}
|
||||
public AsyncDuplexStreamingCall<global::examples.RouteNote, global::examples.RouteNote> RouteChat(CancellationToken token = default(CancellationToken))
|
||||
{
|
||||
var call = CreateCall(__ServiceName, __Method_RouteChat);
|
||||
return Calls.AsyncDuplexStreamingCall(call, token);
|
||||
}
|
||||
}
|
||||
|
||||
// creates service definition that can be registered with a server
|
||||
public static ServerServiceDefinition BindService(IRouteGuide serviceImpl)
|
||||
{
|
||||
return ServerServiceDefinition.CreateBuilder(__ServiceName)
|
||||
.AddMethod(__Method_GetFeature, serviceImpl.GetFeature)
|
||||
.AddMethod(__Method_ListFeatures, serviceImpl.ListFeatures)
|
||||
.AddMethod(__Method_RecordRoute, serviceImpl.RecordRoute)
|
||||
.AddMethod(__Method_RouteChat, serviceImpl.RouteChat).Build();
|
||||
}
|
||||
|
||||
// creates a new client stub
|
||||
public static IRouteGuideClient NewStub(Channel channel)
|
||||
{
|
||||
return new RouteGuideClient(channel);
|
||||
}
|
||||
|
||||
// creates a new client stub
|
||||
public static IRouteGuideClient NewStub(Channel channel, StubConfiguration config)
|
||||
{
|
||||
return new RouteGuideClient(channel, config);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace examples
|
||||
{
|
||||
public static class RouteGuideUtil
|
||||
{
|
||||
public const string DefaultFeaturesFile = "route_guide_db.json";
|
||||
|
||||
private const double CoordFactor = 1e7;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the given feature exists (i.e. has a valid name).
|
||||
/// </summary>
|
||||
public static bool Exists(Feature feature)
|
||||
{
|
||||
return feature != null && (feature.Name.Length != 0);
|
||||
}
|
||||
|
||||
public static double GetLatitude(Point point)
|
||||
{
|
||||
return point.Latitude / CoordFactor;
|
||||
}
|
||||
|
||||
public static double GetLongitude(Point point)
|
||||
{
|
||||
return point.Longitude / CoordFactor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses features from a JSON file.
|
||||
/// </summary>
|
||||
public static List<Feature> ParseFeatures(string filename)
|
||||
{
|
||||
var features = new List<Feature>();
|
||||
var jsonFeatures = JsonConvert.DeserializeObject<List<JsonFeature>>(File.ReadAllText(filename));
|
||||
|
||||
|
||||
foreach(var jsonFeature in jsonFeatures)
|
||||
{
|
||||
features.Add(Feature.CreateBuilder().SetName(jsonFeature.name).SetLocation(
|
||||
Point.CreateBuilder()
|
||||
.SetLongitude(jsonFeature.location.longitude)
|
||||
.SetLatitude(jsonFeature.location.latitude).Build()).Build());
|
||||
}
|
||||
return features;
|
||||
}
|
||||
|
||||
private class JsonFeature
|
||||
{
|
||||
public string name;
|
||||
public JsonLocation location;
|
||||
}
|
||||
|
||||
private class JsonLocation
|
||||
{
|
||||
public int longitude;
|
||||
public int latitude;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Google.ProtocolBuffers" version="2.4.1.555" targetFramework="net45" />
|
||||
<package id="Grpc" version="0.5.0" targetFramework="net45" />
|
||||
<package id="Grpc.Core" version="0.5.0" targetFramework="net45" />
|
||||
<package id="grpc.dependencies.openssl.redist" version="1.0.2.2" targetFramework="net45" />
|
||||
<package id="grpc.dependencies.zlib.redist" version="1.2.8.9" targetFramework="net45" />
|
||||
<package id="grpc.native.csharp_ext" version="0.9.0.0" targetFramework="net45" />
|
||||
<package id="Ix-Async" version="1.2.3" targetFramework="net45" />
|
||||
<package id="Microsoft.Bcl.Immutable" version="1.0.34" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="7.0.1-beta2" targetFramework="net45" />
|
||||
</packages>
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
// 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.
|
||||
|
||||
// TODO(jtattermusch): as of now, C# protobufs don't officially support
|
||||
// proto3.
|
||||
syntax = "proto2";
|
||||
|
||||
package examples;
|
||||
|
||||
// Interface exported by the server.
|
||||
service RouteGuide {
|
||||
// A simple RPC.
|
||||
//
|
||||
// Obtains the feature at a given position.
|
||||
//
|
||||
// A feature with an empty name is returned if there's no feature at the 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,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,6 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
</configuration>
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
using Grpc.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace examples
|
||||
{
|
||||
class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// Sample client code that makes gRPC calls to the server.
|
||||
/// </summary>
|
||||
public class RouteGuideClient
|
||||
{
|
||||
readonly RouteGuide.IRouteGuideClient client;
|
||||
|
||||
public RouteGuideClient(RouteGuide.IRouteGuideClient client)
|
||||
{
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Blocking unary call example. Calls GetFeature and prints the response.
|
||||
/// </summary>
|
||||
public void GetFeature(int lat, int lon)
|
||||
{
|
||||
try
|
||||
{
|
||||
Log("*** GetFeature: lat={0} lon={1}", lat, lon);
|
||||
|
||||
Point request = Point.CreateBuilder().SetLatitude(lat).SetLongitude(lon).Build();
|
||||
|
||||
Feature feature = client.GetFeature(request);
|
||||
if (RouteGuideUtil.Exists(feature))
|
||||
{
|
||||
Log("Found feature called \"{0}\" at {1}, {2}",
|
||||
feature.Name,
|
||||
RouteGuideUtil.GetLatitude(feature.Location),
|
||||
RouteGuideUtil.GetLongitude(feature.Location));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Found no feature at {0}, {1}",
|
||||
RouteGuideUtil.GetLatitude(feature.Location),
|
||||
RouteGuideUtil.GetLongitude(feature.Location));
|
||||
}
|
||||
}
|
||||
catch (RpcException e)
|
||||
{
|
||||
Log("RPC failed " + e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Server-streaming example. Calls listFeatures with a rectangle of interest. Prints each response feature as it arrives.
|
||||
/// </summary>
|
||||
public async Task ListFeatures(int lowLat, int lowLon, int hiLat, int hiLon)
|
||||
{
|
||||
try
|
||||
{
|
||||
Log("*** ListFeatures: lowLat={0} lowLon={1} hiLat={2} hiLon={3}", lowLat, lowLon, hiLat,
|
||||
hiLon);
|
||||
|
||||
Rectangle request =
|
||||
Rectangle.CreateBuilder()
|
||||
.SetLo(Point.CreateBuilder().SetLatitude(lowLat).SetLongitude(lowLon).Build())
|
||||
.SetHi(Point.CreateBuilder().SetLatitude(hiLat).SetLongitude(hiLon).Build()).Build();
|
||||
|
||||
using (var call = client.ListFeatures(request))
|
||||
{
|
||||
StringBuilder responseLog = new StringBuilder("Result: ");
|
||||
|
||||
while (await call.ResponseStream.MoveNext())
|
||||
{
|
||||
Feature feature = call.ResponseStream.Current;
|
||||
responseLog.Append(feature.ToString());
|
||||
}
|
||||
Log(responseLog.ToString());
|
||||
}
|
||||
}
|
||||
catch (RpcException e)
|
||||
{
|
||||
Log("RPC failed " + e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Client-streaming example. Sends numPoints randomly chosen points from features
|
||||
/// with a variable delay in between. Prints the statistics when they are sent from the server.
|
||||
/// </summary>
|
||||
public async Task RecordRoute(List<Feature> features, int numPoints)
|
||||
{
|
||||
try
|
||||
{
|
||||
Log("*** RecordRoute");
|
||||
using (var call = client.RecordRoute())
|
||||
{
|
||||
// Send numPoints points randomly selected from the features list.
|
||||
StringBuilder numMsg = new StringBuilder();
|
||||
Random rand = new Random();
|
||||
for (int i = 0; i < numPoints; ++i)
|
||||
{
|
||||
int index = rand.Next(features.Count);
|
||||
Point point = features[index].Location;
|
||||
Log("Visiting point {0}, {1}", RouteGuideUtil.GetLatitude(point),
|
||||
RouteGuideUtil.GetLongitude(point));
|
||||
|
||||
await call.RequestStream.WriteAsync(point);
|
||||
|
||||
// A bit of delay before sending the next one.
|
||||
await Task.Delay(rand.Next(1000) + 500);
|
||||
}
|
||||
await call.RequestStream.CompleteAsync();
|
||||
|
||||
RouteSummary summary = await call.Result;
|
||||
Log("Finished trip with {0} points. Passed {1} features. "
|
||||
+ "Travelled {2} meters. It took {3} seconds.", summary.PointCount,
|
||||
summary.FeatureCount, summary.Distance, summary.ElapsedTime);
|
||||
|
||||
Log("Finished RecordRoute");
|
||||
}
|
||||
}
|
||||
catch (RpcException e)
|
||||
{
|
||||
Log("RPC failed", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bi-directional streaming example. Send some chat messages, and print any
|
||||
/// chat messages that are sent from the server.
|
||||
/// </summary>
|
||||
public async Task RouteChat()
|
||||
{
|
||||
try
|
||||
{
|
||||
Log("*** RouteChat");
|
||||
var requests =
|
||||
new List<RouteNote> { NewNote("First message", 0, 0), NewNote("Second message", 0, 1), NewNote("Third message", 1, 0), NewNote("Fourth message", 1, 1) };
|
||||
|
||||
using (var call = client.RouteChat())
|
||||
{
|
||||
var responseReaderTask = Task.Run(async () =>
|
||||
{
|
||||
while (await call.ResponseStream.MoveNext())
|
||||
{
|
||||
var note = call.ResponseStream.Current;
|
||||
Log("Got message \"{0}\" at {1}, {2}", note.Message,
|
||||
note.Location.Latitude, note.Location.Longitude);
|
||||
}
|
||||
});
|
||||
|
||||
foreach (RouteNote request in requests)
|
||||
{
|
||||
Log("Sending message \"{0}\" at {1}, {2}", request.Message,
|
||||
request.Location.Latitude, request.Location.Longitude);
|
||||
|
||||
await call.RequestStream.WriteAsync(request);
|
||||
}
|
||||
await call.RequestStream.CompleteAsync();
|
||||
await responseReaderTask;
|
||||
|
||||
Log("Finished RouteChat");
|
||||
}
|
||||
}
|
||||
catch (RpcException e)
|
||||
{
|
||||
Log("RPC failed", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private void Log(string s, params object[] args)
|
||||
{
|
||||
Console.WriteLine(string.Format(s, args));
|
||||
}
|
||||
|
||||
private void Log(string s)
|
||||
{
|
||||
Console.WriteLine(s);
|
||||
}
|
||||
|
||||
private RouteNote NewNote(string message, int lat, int lon)
|
||||
{
|
||||
return RouteNote.CreateBuilder().SetMessage(message).SetLocation(
|
||||
Point.CreateBuilder().SetLatitude(lat).SetLongitude(lat).Build()).Build();
|
||||
}
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
GrpcEnvironment.Initialize();
|
||||
|
||||
using (Channel channel = new Channel("127.0.0.1:50052"))
|
||||
{
|
||||
var client = new RouteGuideClient(RouteGuide.NewStub(channel));
|
||||
|
||||
// Looking for a valid feature
|
||||
client.GetFeature(409146138, -746188906);
|
||||
|
||||
// Feature missing.
|
||||
client.GetFeature(0, 0);
|
||||
|
||||
// Looking for features between 40, -75 and 42, -73.
|
||||
client.ListFeatures(400000000, -750000000, 420000000, -730000000).Wait();
|
||||
|
||||
// Record a few randomly selected points from the features file.
|
||||
client.RecordRoute(RouteGuideUtil.ParseFeatures(RouteGuideUtil.DefaultFeaturesFile), 10).Wait();
|
||||
|
||||
// Send and receive some notes.
|
||||
client.RouteChat().Wait();
|
||||
}
|
||||
|
||||
GrpcEnvironment.Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("RouteGuideClient")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("RouteGuideClient")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("914644eb-47cd-4a37-9fba-5e62dd432333")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.props" Condition="Exists('..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.props')" />
|
||||
<Import Project="..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props" Condition="Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props')" />
|
||||
<Import Project="..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props" Condition="Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{D47BE663-4DE3-4206-B7A8-EA3FA066DADC}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>RouteGuideClient</RootNamespace>
|
||||
<AssemblyName>RouteGuideClient</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<NuGetPackageImportStamp>c0fbb9f1</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Google.ProtocolBuffers">
|
||||
<HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Google.ProtocolBuffers.Serialization">
|
||||
<HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.Serialization.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Grpc.Core">
|
||||
<HintPath>..\packages\Grpc.Core.0.5.0\lib\net45\Grpc.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Collections.Immutable">
|
||||
<HintPath>..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Interactive.Async">
|
||||
<HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\RouteGuide\RouteGuide.csproj">
|
||||
<Project>{49954d9c-5f17-4662-96b2-73be833dd81a}</Project>
|
||||
<Name>RouteGuide</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props'))" />
|
||||
<Error Condition="!Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props'))" />
|
||||
<Error Condition="!Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.props'))" />
|
||||
<Error Condition="!Exists('..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets')" />
|
||||
<Import Project="..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets')" />
|
||||
<Import Project="..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.targets" Condition="Exists('..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.targets')" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Google.ProtocolBuffers" version="2.4.1.555" targetFramework="net45" />
|
||||
<package id="Grpc" version="0.5.0" targetFramework="net45" />
|
||||
<package id="Grpc.Core" version="0.5.0" targetFramework="net45" />
|
||||
<package id="grpc.dependencies.openssl.redist" version="1.0.2.2" targetFramework="net45" />
|
||||
<package id="grpc.dependencies.zlib.redist" version="1.2.8.9" targetFramework="net45" />
|
||||
<package id="grpc.native.csharp_ext" version="0.9.0.0" targetFramework="net45" />
|
||||
<package id="Ix-Async" version="1.2.3" targetFramework="net45" />
|
||||
<package id="Microsoft.Bcl.Immutable" version="1.0.34" targetFramework="net45" />
|
||||
</packages>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
</configuration>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
using Grpc.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace examples
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var features = RouteGuideUtil.ParseFeatures(RouteGuideUtil.DefaultFeaturesFile);
|
||||
GrpcEnvironment.Initialize();
|
||||
|
||||
Server server = new Server();
|
||||
server.AddServiceDefinition(RouteGuide.BindService(new RouteGuideImpl(features)));
|
||||
int port = server.AddListeningPort("localhost", 50052);
|
||||
server.Start();
|
||||
|
||||
Console.WriteLine("RouteGuide server listening on port " + port);
|
||||
Console.WriteLine("Press any key to stop the server...");
|
||||
Console.ReadKey();
|
||||
|
||||
server.ShutdownAsync().Wait();
|
||||
GrpcEnvironment.Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("RouteGuideServer")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("RouteGuideServer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("908bdeef-05cc-42bf-9498-c4c573df8925")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace examples
|
||||
{
|
||||
/// <summary>
|
||||
/// Example implementation of RouteGuide server.
|
||||
/// </summary>
|
||||
public class RouteGuideImpl : RouteGuide.IRouteGuide
|
||||
{
|
||||
readonly List<Feature> features;
|
||||
private readonly ConcurrentDictionary<Point, List<RouteNote>> routeNotes =
|
||||
new ConcurrentDictionary<Point, List<RouteNote>>();
|
||||
|
||||
public RouteGuideImpl(List<Feature> features)
|
||||
{
|
||||
this.features = features;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the feature at the requested point. If no feature at that location
|
||||
/// exists, an unnammed feature is returned at the provided location.
|
||||
/// </summary>
|
||||
public Task<Feature> GetFeature(Grpc.Core.ServerCallContext context, Point request)
|
||||
{
|
||||
return Task.FromResult(CheckFeature(request));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all features contained within the given bounding rectangle.
|
||||
/// </summary>
|
||||
public async Task ListFeatures(Grpc.Core.ServerCallContext context, Rectangle request, Grpc.Core.IServerStreamWriter<Feature> responseStream)
|
||||
{
|
||||
int left = Math.Min(request.Lo.Longitude, request.Hi.Longitude);
|
||||
int right = Math.Max(request.Lo.Longitude, request.Hi.Longitude);
|
||||
int top = Math.Max(request.Lo.Latitude, request.Hi.Latitude);
|
||||
int bottom = Math.Min(request.Lo.Latitude, request.Hi.Latitude);
|
||||
|
||||
foreach (var feature in features)
|
||||
{
|
||||
if (!RouteGuideUtil.Exists(feature))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int lat = feature.Location.Latitude;
|
||||
int lon = feature.Location.Longitude;
|
||||
if (lon >= left && lon <= right && lat >= bottom && lat <= top)
|
||||
{
|
||||
await responseStream.WriteAsync(feature);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public async Task<RouteSummary> RecordRoute(Grpc.Core.ServerCallContext context, Grpc.Core.IAsyncStreamReader<Point> requestStream)
|
||||
{
|
||||
int pointCount = 0;
|
||||
int featureCount = 0;
|
||||
int distance = 0;
|
||||
Point previous = null;
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
while (await requestStream.MoveNext())
|
||||
{
|
||||
var point = requestStream.Current;
|
||||
pointCount++;
|
||||
if (RouteGuideUtil.Exists(CheckFeature(point)))
|
||||
{
|
||||
featureCount++;
|
||||
}
|
||||
if (previous != null)
|
||||
{
|
||||
distance += (int) CalcDistance(previous, point);
|
||||
}
|
||||
previous = point;
|
||||
}
|
||||
|
||||
stopwatch.Stop();
|
||||
return RouteSummary.CreateBuilder().SetPointCount(pointCount)
|
||||
.SetFeatureCount(featureCount).SetDistance(distance)
|
||||
.SetElapsedTime((int) (stopwatch.ElapsedMilliseconds / 1000)).Build();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Receives a stream of message/location pairs, and responds with a stream of all previous
|
||||
/// messages at each of those locations.
|
||||
/// </summary>
|
||||
public async Task RouteChat(Grpc.Core.ServerCallContext context, Grpc.Core.IAsyncStreamReader<RouteNote> requestStream, Grpc.Core.IServerStreamWriter<RouteNote> responseStream)
|
||||
{
|
||||
while (await requestStream.MoveNext())
|
||||
{
|
||||
var note = requestStream.Current;
|
||||
List<RouteNote> notes = GetOrCreateNotes(note.Location);
|
||||
|
||||
List<RouteNote> prevNotes;
|
||||
lock (notes)
|
||||
{
|
||||
prevNotes = new List<RouteNote>(notes);
|
||||
}
|
||||
|
||||
foreach (var prevNote in prevNotes)
|
||||
{
|
||||
await responseStream.WriteAsync(prevNote);
|
||||
}
|
||||
|
||||
lock (notes)
|
||||
{
|
||||
notes.Add(note);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the notes list for the given location. If missing, create it.
|
||||
/// </summary>
|
||||
private List<RouteNote> GetOrCreateNotes(Point location)
|
||||
{
|
||||
List<RouteNote> notes = new List<RouteNote>();
|
||||
routeNotes.TryAdd(location, notes);
|
||||
return routeNotes[location];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the feature at the given point.
|
||||
/// </summary>
|
||||
/// <param name="location">the location to check</param>
|
||||
/// <returns>The feature object at the point Note that an empty name indicates no feature.</returns>
|
||||
private Feature CheckFeature(Point location)
|
||||
{
|
||||
foreach (var feature in features)
|
||||
{
|
||||
if (feature.Location.Latitude == location.Latitude
|
||||
&& feature.Location.Longitude == location.Longitude)
|
||||
{
|
||||
return feature;
|
||||
}
|
||||
}
|
||||
|
||||
// No feature was found, return an unnamed feature.
|
||||
return Feature.CreateBuilder().SetName("").SetLocation(location).Build();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the distance between two points using the "haversine" formula.
|
||||
/// This code was taken from http://www.movable-type.co.uk/scripts/latlong.html.
|
||||
/// </summary>
|
||||
/// <param name="start">the starting point</param>
|
||||
/// <param name="end">the end point</param>
|
||||
/// <returns>the distance between the points in meters</returns>
|
||||
private static double CalcDistance(Point start, Point end)
|
||||
{
|
||||
double lat1 = RouteGuideUtil.GetLatitude(start);
|
||||
double lat2 = RouteGuideUtil.GetLatitude(end);
|
||||
double lon1 = RouteGuideUtil.GetLongitude(start);
|
||||
double lon2 = RouteGuideUtil.GetLongitude(end);
|
||||
int r = 6371000; // metres
|
||||
double φ1 = ToRadians(lat1);
|
||||
double φ2 = ToRadians(lat2);
|
||||
double Δφ = ToRadians(lat2 - lat1);
|
||||
double Δλ = ToRadians(lon2 - lon1);
|
||||
|
||||
double a = Math.Sin(Δφ / 2) * Math.Sin(Δφ / 2) + Math.Cos(φ1) * Math.Cos(φ2) * Math.Sin(Δλ / 2) * Math.Sin(Δλ / 2);
|
||||
double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
|
||||
|
||||
return r * c;
|
||||
}
|
||||
|
||||
private static double ToRadians(double val)
|
||||
{
|
||||
return (Math.PI / 180) * val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.props" Condition="Exists('..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.props')" />
|
||||
<Import Project="..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props" Condition="Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props')" />
|
||||
<Import Project="..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props" Condition="Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{4B7C7794-BE24-4477-ACE7-18259EB73D27}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>RouteGuideServer</RootNamespace>
|
||||
<AssemblyName>RouteGuideServer</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<NuGetPackageImportStamp>93b8fc4b</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Google.ProtocolBuffers">
|
||||
<HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Google.ProtocolBuffers.Serialization">
|
||||
<HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.Serialization.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Grpc.Core">
|
||||
<HintPath>..\packages\Grpc.Core.0.5.0\lib\net45\Grpc.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Collections.Immutable">
|
||||
<HintPath>..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Interactive.Async">
|
||||
<HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="RouteGuideImpl.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\RouteGuide\RouteGuide.csproj">
|
||||
<Project>{49954d9c-5f17-4662-96b2-73be833dd81a}</Project>
|
||||
<Name>RouteGuide</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props'))" />
|
||||
<Error Condition="!Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props'))" />
|
||||
<Error Condition="!Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.props'))" />
|
||||
<Error Condition="!Exists('..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets')" />
|
||||
<Import Project="..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets')" />
|
||||
<Import Project="..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.targets" Condition="Exists('..\packages\grpc.native.csharp_ext.0.9.0.0\build\portable-net45\grpc.native.csharp_ext.targets')" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Google.ProtocolBuffers" version="2.4.1.555" targetFramework="net45" />
|
||||
<package id="Grpc" version="0.5.0" targetFramework="net45" />
|
||||
<package id="Grpc.Core" version="0.5.0" targetFramework="net45" />
|
||||
<package id="grpc.dependencies.openssl.redist" version="1.0.2.2" targetFramework="net45" />
|
||||
<package id="grpc.dependencies.zlib.redist" version="1.2.8.9" targetFramework="net45" />
|
||||
<package id="grpc.native.csharp_ext" version="0.9.0.0" targetFramework="net45" />
|
||||
<package id="Ix-Async" version="1.2.3" targetFramework="net45" />
|
||||
<package id="Microsoft.Bcl.Immutable" version="1.0.34" targetFramework="net45" />
|
||||
</packages>
|
||||
Loading…
Reference in New Issue