一、引言

  本文采用gRPC官方提供的一个教程例子,通过这个例子可以学习到在.proto文件中定义服务。使用protocol buffer编译器生成服务器和客户端代码。使用C#gRPC API为您的服务编写简单的客户端和服务器。具体可参看:https://grpc.io/docs/tutorials/basic/csharp/

二、具体步骤

  • 定义.proto文件
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License. syntax = "proto3"; option java_multiple_files = true;
option java_package = "io.grpc.examples.routeguide";
option java_outer_classname = "RouteGuideProto";
option objc_class_prefix = "RTG"; package routeguide; // 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 {
int32 latitude = ;
int32 longitude = ;
} // A latitude-longitude rectangle, represented as two diagonally opposite
// points "lo" and "hi".
message Rectangle {
// One corner of the rectangle.
Point lo = ; // The other corner of the rectangle.
Point hi = ;
} // A feature names something at a given point.
//
// If a feature could not be named, the name is empty.
message Feature {
// The name of the feature.
string name = ; // The point where the feature is detected.
Point location = ;
} // A RouteNote is a message sent while at a given point.
message RouteNote {
// The location from which the message is sent.
Point location = ; // The message to be sent.
string message = ;
} // A RouteSummary is received in response to a RecordRoute rpc.
//
// It contains the number of individual points received, the number of
// detected features, and the total distance covered as the cumulative sum of
// the distance between each point.
message RouteSummary {
// The number of points received.
int32 point_count = ; // The number of known features passed while traversing the route.
int32 feature_count = ; // The distance covered in metres.
int32 distance = ; // The duration of the traversal in seconds.
int32 elapsed_time = ;
}
  • 需要引入Nuget包
Install-Package Google.Protobuf
Install-Package Grpc
Install-Package Grpc.Tools
  • 生成客户端和服务器代码,在Grpc.Tools 1.17版本之后 Grpc.ToolsNuGet包与MSBuild集成从.proto文件自动生成C#代码。但是在1.17以前的版本需要使用protoc.exe和grpc_csharp_plugin.exe 来生成代码,如下命令:
protoc -I . --csharp_out . --grpc_out . --plugin=protoc-gen-grpc=grpc_csharp_plugin.exe Helloworld.proto

  在Grpc.Tools 1.17版本之后只需要使用donet build RouteGuid.sln或者直接在Visual Studio构建项目来完成,构建重新生成目录下的以下文件RouteGuide/obj/Debug/TARGET_FRAMEWORK:RouteGuide.cs和RouteGuideGrpc.cs

// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: route_guide.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Routeguide { /// <summary>Holder for reflection information generated from route_guide.proto</summary>
public static partial class RouteGuideReflection { #region Descriptor
/// <summary>File descriptor for route_guide.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor; static RouteGuideReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"ChFyb3V0ZV9ndWlkZS5wcm90bxIKcm91dGVndWlkZSIsCgVQb2ludBIQCghs",
"YXRpdHVkZRgBIAEoBRIRCglsb25naXR1ZGUYAiABKAUiSQoJUmVjdGFuZ2xl",
"Eh0KAmxvGAEgASgLMhEucm91dGVndWlkZS5Qb2ludBIdCgJoaRgCIAEoCzIR",
"LnJvdXRlZ3VpZGUuUG9pbnQiPAoHRmVhdHVyZRIMCgRuYW1lGAEgASgJEiMK",
"CGxvY2F0aW9uGAIgASgLMhEucm91dGVndWlkZS5Qb2ludCJBCglSb3V0ZU5v",
"dGUSIwoIbG9jYXRpb24YASABKAsyES5yb3V0ZWd1aWRlLlBvaW50Eg8KB21l",
"c3NhZ2UYAiABKAkiYgoMUm91dGVTdW1tYXJ5EhMKC3BvaW50X2NvdW50GAEg",
"ASgFEhUKDWZlYXR1cmVfY291bnQYAiABKAUSEAoIZGlzdGFuY2UYAyABKAUS",
"FAoMZWxhcHNlZF90aW1lGAQgASgFMoUCCgpSb3V0ZUd1aWRlEjYKCkdldEZl",
"YXR1cmUSES5yb3V0ZWd1aWRlLlBvaW50GhMucm91dGVndWlkZS5GZWF0dXJl",
"IgASPgoMTGlzdEZlYXR1cmVzEhUucm91dGVndWlkZS5SZWN0YW5nbGUaEy5y",
"b3V0ZWd1aWRlLkZlYXR1cmUiADABEj4KC1JlY29yZFJvdXRlEhEucm91dGVn",
"dWlkZS5Qb2ludBoYLnJvdXRlZ3VpZGUuUm91dGVTdW1tYXJ5IgAoARI/CglS",
"b3V0ZUNoYXQSFS5yb3V0ZWd1aWRlLlJvdXRlTm90ZRoVLnJvdXRlZ3VpZGUu",
"Um91dGVOb3RlIgAoATABQjYKG2lvLmdycGMuZXhhbXBsZXMucm91dGVndWlk",
"ZUIPUm91dGVHdWlkZVByb3RvUAGiAgNSVEdiBnByb3RvMw=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::Routeguide.Point), global::Routeguide.Point.Parser, new[]{ "Latitude", "Longitude" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Routeguide.Rectangle), global::Routeguide.Rectangle.Parser, new[]{ "Lo", "Hi" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Routeguide.Feature), global::Routeguide.Feature.Parser, new[]{ "Name", "Location" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Routeguide.RouteNote), global::Routeguide.RouteNote.Parser, new[]{ "Location", "Message" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Routeguide.RouteSummary), global::Routeguide.RouteSummary.Parser, new[]{ "PointCount", "FeatureCount", "Distance", "ElapsedTime" }, null, null, null)
}));
}
#endregion }
#region Messages
/// <summary>
/// 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).
/// </summary>
public sealed partial class Point : pb::IMessage<Point> {
private static readonly pb::MessageParser<Point> _parser = new pb::MessageParser<Point>(() => new Point());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Point> Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[]; }
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Point() {
OnConstruction();
} partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Point(Point other) : this() {
latitude_ = other.latitude_;
longitude_ = other.longitude_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Point Clone() {
return new Point(this);
} /// <summary>Field number for the "latitude" field.</summary>
public const int LatitudeFieldNumber = ;
private int latitude_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int Latitude {
get { return latitude_; }
set {
latitude_ = value;
}
} /// <summary>Field number for the "longitude" field.</summary>
public const int LongitudeFieldNumber = ;
private int longitude_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int Longitude {
get { return longitude_; }
set {
longitude_ = value;
}
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as Point);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(Point other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Latitude != other.Latitude) return false;
if (Longitude != other.Longitude) return false;
return Equals(_unknownFields, other._unknownFields);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = ;
if (Latitude != ) hash ^= Latitude.GetHashCode();
if (Longitude != ) hash ^= Longitude.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
if (Latitude != ) {
output.WriteRawTag();
output.WriteInt32(Latitude);
}
if (Longitude != ) {
output.WriteRawTag();
output.WriteInt32(Longitude);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = ;
if (Latitude != ) {
size += + pb::CodedOutputStream.ComputeInt32Size(Latitude);
}
if (Longitude != ) {
size += + pb::CodedOutputStream.ComputeInt32Size(Longitude);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(Point other) {
if (other == null) {
return;
}
if (other.Latitude != ) {
Latitude = other.Latitude;
}
if (other.Longitude != ) {
Longitude = other.Longitude;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != ) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case : {
Latitude = input.ReadInt32();
break;
}
case : {
Longitude = input.ReadInt32();
break;
}
}
}
} } /// <summary>
/// A latitude-longitude rectangle, represented as two diagonally opposite
/// points "lo" and "hi".
/// </summary>
public sealed partial class Rectangle : pb::IMessage<Rectangle> {
private static readonly pb::MessageParser<Rectangle> _parser = new pb::MessageParser<Rectangle>(() => new Rectangle());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Rectangle> Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[]; }
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Rectangle() {
OnConstruction();
} partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Rectangle(Rectangle other) : this() {
lo_ = other.lo_ != null ? other.lo_.Clone() : null;
hi_ = other.hi_ != null ? other.hi_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Rectangle Clone() {
return new Rectangle(this);
} /// <summary>Field number for the "lo" field.</summary>
public const int LoFieldNumber = ;
private global::Routeguide.Point lo_;
/// <summary>
/// One corner of the rectangle.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Routeguide.Point Lo {
get { return lo_; }
set {
lo_ = value;
}
} /// <summary>Field number for the "hi" field.</summary>
public const int HiFieldNumber = ;
private global::Routeguide.Point hi_;
/// <summary>
/// The other corner of the rectangle.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Routeguide.Point Hi {
get { return hi_; }
set {
hi_ = value;
}
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as Rectangle);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(Rectangle other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (!object.Equals(Lo, other.Lo)) return false;
if (!object.Equals(Hi, other.Hi)) return false;
return Equals(_unknownFields, other._unknownFields);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = ;
if (lo_ != null) hash ^= Lo.GetHashCode();
if (hi_ != null) hash ^= Hi.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
if (lo_ != null) {
output.WriteRawTag();
output.WriteMessage(Lo);
}
if (hi_ != null) {
output.WriteRawTag();
output.WriteMessage(Hi);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = ;
if (lo_ != null) {
size += + pb::CodedOutputStream.ComputeMessageSize(Lo);
}
if (hi_ != null) {
size += + pb::CodedOutputStream.ComputeMessageSize(Hi);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(Rectangle other) {
if (other == null) {
return;
}
if (other.lo_ != null) {
if (lo_ == null) {
lo_ = new global::Routeguide.Point();
}
Lo.MergeFrom(other.Lo);
}
if (other.hi_ != null) {
if (hi_ == null) {
hi_ = new global::Routeguide.Point();
}
Hi.MergeFrom(other.Hi);
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != ) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case : {
if (lo_ == null) {
lo_ = new global::Routeguide.Point();
}
input.ReadMessage(lo_);
break;
}
case : {
if (hi_ == null) {
hi_ = new global::Routeguide.Point();
}
input.ReadMessage(hi_);
break;
}
}
}
} } /// <summary>
/// A feature names something at a given point.
///
/// If a feature could not be named, the name is empty.
/// </summary>
public sealed partial class Feature : pb::IMessage<Feature> {
private static readonly pb::MessageParser<Feature> _parser = new pb::MessageParser<Feature>(() => new Feature());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Feature> Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[]; }
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Feature() {
OnConstruction();
} partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Feature(Feature other) : this() {
name_ = other.name_;
location_ = other.location_ != null ? other.location_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Feature Clone() {
return new Feature(this);
} /// <summary>Field number for the "name" field.</summary>
public const int NameFieldNumber = ;
private string name_ = "";
/// <summary>
/// The name of the feature.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Name {
get { return name_; }
set {
name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
} /// <summary>Field number for the "location" field.</summary>
public const int LocationFieldNumber = ;
private global::Routeguide.Point location_;
/// <summary>
/// The point where the feature is detected.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Routeguide.Point Location {
get { return location_; }
set {
location_ = value;
}
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as Feature);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(Feature other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Name != other.Name) return false;
if (!object.Equals(Location, other.Location)) return false;
return Equals(_unknownFields, other._unknownFields);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = ;
if (Name.Length != ) hash ^= Name.GetHashCode();
if (location_ != null) hash ^= Location.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
if (Name.Length != ) {
output.WriteRawTag();
output.WriteString(Name);
}
if (location_ != null) {
output.WriteRawTag();
output.WriteMessage(Location);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = ;
if (Name.Length != ) {
size += + pb::CodedOutputStream.ComputeStringSize(Name);
}
if (location_ != null) {
size += + pb::CodedOutputStream.ComputeMessageSize(Location);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(Feature other) {
if (other == null) {
return;
}
if (other.Name.Length != ) {
Name = other.Name;
}
if (other.location_ != null) {
if (location_ == null) {
location_ = new global::Routeguide.Point();
}
Location.MergeFrom(other.Location);
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != ) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case : {
Name = input.ReadString();
break;
}
case : {
if (location_ == null) {
location_ = new global::Routeguide.Point();
}
input.ReadMessage(location_);
break;
}
}
}
} } /// <summary>
/// A RouteNote is a message sent while at a given point.
/// </summary>
public sealed partial class RouteNote : pb::IMessage<RouteNote> {
private static readonly pb::MessageParser<RouteNote> _parser = new pb::MessageParser<RouteNote>(() => new RouteNote());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<RouteNote> Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[]; }
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public RouteNote() {
OnConstruction();
} partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public RouteNote(RouteNote other) : this() {
location_ = other.location_ != null ? other.location_.Clone() : null;
message_ = other.message_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public RouteNote Clone() {
return new RouteNote(this);
} /// <summary>Field number for the "location" field.</summary>
public const int LocationFieldNumber = ;
private global::Routeguide.Point location_;
/// <summary>
/// The location from which the message is sent.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Routeguide.Point Location {
get { return location_; }
set {
location_ = value;
}
} /// <summary>Field number for the "message" field.</summary>
public const int MessageFieldNumber = ;
private string message_ = "";
/// <summary>
/// The message to be sent.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Message {
get { return message_; }
set {
message_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as RouteNote);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(RouteNote other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (!object.Equals(Location, other.Location)) return false;
if (Message != other.Message) return false;
return Equals(_unknownFields, other._unknownFields);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = ;
if (location_ != null) hash ^= Location.GetHashCode();
if (Message.Length != ) hash ^= Message.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
if (location_ != null) {
output.WriteRawTag();
output.WriteMessage(Location);
}
if (Message.Length != ) {
output.WriteRawTag();
output.WriteString(Message);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = ;
if (location_ != null) {
size += + pb::CodedOutputStream.ComputeMessageSize(Location);
}
if (Message.Length != ) {
size += + pb::CodedOutputStream.ComputeStringSize(Message);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(RouteNote other) {
if (other == null) {
return;
}
if (other.location_ != null) {
if (location_ == null) {
location_ = new global::Routeguide.Point();
}
Location.MergeFrom(other.Location);
}
if (other.Message.Length != ) {
Message = other.Message;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != ) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case : {
if (location_ == null) {
location_ = new global::Routeguide.Point();
}
input.ReadMessage(location_);
break;
}
case : {
Message = input.ReadString();
break;
}
}
}
} } /// <summary>
/// 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.
/// </summary>
public sealed partial class RouteSummary : pb::IMessage<RouteSummary> {
private static readonly pb::MessageParser<RouteSummary> _parser = new pb::MessageParser<RouteSummary>(() => new RouteSummary());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<RouteSummary> Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[]; }
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public RouteSummary() {
OnConstruction();
} partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public RouteSummary(RouteSummary other) : this() {
pointCount_ = other.pointCount_;
featureCount_ = other.featureCount_;
distance_ = other.distance_;
elapsedTime_ = other.elapsedTime_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public RouteSummary Clone() {
return new RouteSummary(this);
} /// <summary>Field number for the "point_count" field.</summary>
public const int PointCountFieldNumber = ;
private int pointCount_;
/// <summary>
/// The number of points received.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int PointCount {
get { return pointCount_; }
set {
pointCount_ = value;
}
} /// <summary>Field number for the "feature_count" field.</summary>
public const int FeatureCountFieldNumber = ;
private int featureCount_;
/// <summary>
/// The number of known features passed while traversing the route.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int FeatureCount {
get { return featureCount_; }
set {
featureCount_ = value;
}
} /// <summary>Field number for the "distance" field.</summary>
public const int DistanceFieldNumber = ;
private int distance_;
/// <summary>
/// The distance covered in metres.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int Distance {
get { return distance_; }
set {
distance_ = value;
}
} /// <summary>Field number for the "elapsed_time" field.</summary>
public const int ElapsedTimeFieldNumber = ;
private int elapsedTime_;
/// <summary>
/// The duration of the traversal in seconds.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int ElapsedTime {
get { return elapsedTime_; }
set {
elapsedTime_ = value;
}
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as RouteSummary);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(RouteSummary other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (PointCount != other.PointCount) return false;
if (FeatureCount != other.FeatureCount) return false;
if (Distance != other.Distance) return false;
if (ElapsedTime != other.ElapsedTime) return false;
return Equals(_unknownFields, other._unknownFields);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = ;
if (PointCount != ) hash ^= PointCount.GetHashCode();
if (FeatureCount != ) hash ^= FeatureCount.GetHashCode();
if (Distance != ) hash ^= Distance.GetHashCode();
if (ElapsedTime != ) hash ^= ElapsedTime.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
if (PointCount != ) {
output.WriteRawTag();
output.WriteInt32(PointCount);
}
if (FeatureCount != ) {
output.WriteRawTag();
output.WriteInt32(FeatureCount);
}
if (Distance != ) {
output.WriteRawTag();
output.WriteInt32(Distance);
}
if (ElapsedTime != ) {
output.WriteRawTag();
output.WriteInt32(ElapsedTime);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = ;
if (PointCount != ) {
size += + pb::CodedOutputStream.ComputeInt32Size(PointCount);
}
if (FeatureCount != ) {
size += + pb::CodedOutputStream.ComputeInt32Size(FeatureCount);
}
if (Distance != ) {
size += + pb::CodedOutputStream.ComputeInt32Size(Distance);
}
if (ElapsedTime != ) {
size += + pb::CodedOutputStream.ComputeInt32Size(ElapsedTime);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(RouteSummary other) {
if (other == null) {
return;
}
if (other.PointCount != ) {
PointCount = other.PointCount;
}
if (other.FeatureCount != ) {
FeatureCount = other.FeatureCount;
}
if (other.Distance != ) {
Distance = other.Distance;
}
if (other.ElapsedTime != ) {
ElapsedTime = other.ElapsedTime;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != ) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case : {
PointCount = input.ReadInt32();
break;
}
case : {
FeatureCount = input.ReadInt32();
break;
}
case : {
Distance = input.ReadInt32();
break;
}
case : {
ElapsedTime = input.ReadInt32();
break;
}
}
}
} } #endregion } #endregion Designer generated code
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: route_guide.proto
// </auto-generated>
// Original file comments:
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#pragma warning disable 0414, 1591
#region Designer generated code using grpc = global::Grpc.Core; namespace Routeguide {
/// <summary>
/// Interface exported by the server.
/// </summary>
public static partial class RouteGuide
{
static readonly string __ServiceName = "routeguide.RouteGuide"; static readonly grpc::Marshaller<global::Routeguide.Point> __Marshaller_routeguide_Point = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.Point.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Routeguide.Feature> __Marshaller_routeguide_Feature = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.Feature.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Routeguide.Rectangle> __Marshaller_routeguide_Rectangle = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.Rectangle.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Routeguide.RouteSummary> __Marshaller_routeguide_RouteSummary = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.RouteSummary.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Routeguide.RouteNote> __Marshaller_routeguide_RouteNote = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.RouteNote.Parser.ParseFrom); static readonly grpc::Method<global::Routeguide.Point, global::Routeguide.Feature> __Method_GetFeature = new grpc::Method<global::Routeguide.Point, global::Routeguide.Feature>(
grpc::MethodType.Unary,
__ServiceName,
"GetFeature",
__Marshaller_routeguide_Point,
__Marshaller_routeguide_Feature); static readonly grpc::Method<global::Routeguide.Rectangle, global::Routeguide.Feature> __Method_ListFeatures = new grpc::Method<global::Routeguide.Rectangle, global::Routeguide.Feature>(
grpc::MethodType.ServerStreaming,
__ServiceName,
"ListFeatures",
__Marshaller_routeguide_Rectangle,
__Marshaller_routeguide_Feature); static readonly grpc::Method<global::Routeguide.Point, global::Routeguide.RouteSummary> __Method_RecordRoute = new grpc::Method<global::Routeguide.Point, global::Routeguide.RouteSummary>(
grpc::MethodType.ClientStreaming,
__ServiceName,
"RecordRoute",
__Marshaller_routeguide_Point,
__Marshaller_routeguide_RouteSummary); static readonly grpc::Method<global::Routeguide.RouteNote, global::Routeguide.RouteNote> __Method_RouteChat = new grpc::Method<global::Routeguide.RouteNote, global::Routeguide.RouteNote>(
grpc::MethodType.DuplexStreaming,
__ServiceName,
"RouteChat",
__Marshaller_routeguide_RouteNote,
__Marshaller_routeguide_RouteNote); /// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Routeguide.RouteGuideReflection.Descriptor.Services[]; }
} /// <summary>Base class for server-side implementations of RouteGuide</summary>
public abstract partial class RouteGuideBase
{
/// <summary>
/// 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.
/// </summary>
/// <param name="request">The request received from the client.</param>
/// <param name="context">The context of the server-side call handler being invoked.</param>
/// <returns>The response to send back to the client (wrapped by a task).</returns>
public virtual global::System.Threading.Tasks.Task<global::Routeguide.Feature> GetFeature(global::Routeguide.Point request, grpc::ServerCallContext context)
{
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
} /// <summary>
/// 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.
/// </summary>
/// <param name="request">The request received from the client.</param>
/// <param name="responseStream">Used for sending responses back to the client.</param>
/// <param name="context">The context of the server-side call handler being invoked.</param>
/// <returns>A task indicating completion of the handler.</returns>
public virtual global::System.Threading.Tasks.Task ListFeatures(global::Routeguide.Rectangle request, grpc::IServerStreamWriter<global::Routeguide.Feature> responseStream, grpc::ServerCallContext context)
{
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
} /// <summary>
/// A client-to-server streaming RPC.
///
/// Accepts a stream of Points on a route being traversed, returning a
/// RouteSummary when traversal is completed.
/// </summary>
/// <param name="requestStream">Used for reading requests from the client.</param>
/// <param name="context">The context of the server-side call handler being invoked.</param>
/// <returns>The response to send back to the client (wrapped by a task).</returns>
public virtual global::System.Threading.Tasks.Task<global::Routeguide.RouteSummary> RecordRoute(grpc::IAsyncStreamReader<global::Routeguide.Point> requestStream, grpc::ServerCallContext context)
{
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
} /// <summary>
/// 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).
/// </summary>
/// <param name="requestStream">Used for reading requests from the client.</param>
/// <param name="responseStream">Used for sending responses back to the client.</param>
/// <param name="context">The context of the server-side call handler being invoked.</param>
/// <returns>A task indicating completion of the handler.</returns>
public virtual global::System.Threading.Tasks.Task RouteChat(grpc::IAsyncStreamReader<global::Routeguide.RouteNote> requestStream, grpc::IServerStreamWriter<global::Routeguide.RouteNote> responseStream, grpc::ServerCallContext context)
{
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
} } /// <summary>Client for RouteGuide</summary>
public partial class RouteGuideClient : grpc::ClientBase<RouteGuideClient>
{
/// <summary>Creates a new client for RouteGuide</summary>
/// <param name="channel">The channel to use to make remote calls.</param>
public RouteGuideClient(grpc::Channel channel) : base(channel)
{
}
/// <summary>Creates a new client for RouteGuide that uses a custom <c>CallInvoker</c>.</summary>
/// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
public RouteGuideClient(grpc::CallInvoker callInvoker) : base(callInvoker)
{
}
/// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected RouteGuideClient() : base()
{
}
/// <summary>Protected constructor to allow creation of configured clients.</summary>
/// <param name="configuration">The client configuration.</param>
protected RouteGuideClient(ClientBaseConfiguration configuration) : base(configuration)
{
} /// <summary>
/// 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.
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The response received from the server.</returns>
public virtual global::Routeguide.Feature GetFeature(global::Routeguide.Point request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return GetFeature(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// 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.
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="options">The options for the call.</param>
/// <returns>The response received from the server.</returns>
public virtual global::Routeguide.Feature GetFeature(global::Routeguide.Point request, grpc::CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_GetFeature, null, options, request);
}
/// <summary>
/// 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.
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return GetFeatureAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// 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.
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="options">The options for the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, grpc::CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_GetFeature, null, options, request);
}
/// <summary>
/// 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.
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncServerStreamingCall<global::Routeguide.Feature> ListFeatures(global::Routeguide.Rectangle request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return ListFeatures(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// 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.
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="options">The options for the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncServerStreamingCall<global::Routeguide.Feature> ListFeatures(global::Routeguide.Rectangle request, grpc::CallOptions options)
{
return CallInvoker.AsyncServerStreamingCall(__Method_ListFeatures, null, options, request);
}
/// <summary>
/// A client-to-server streaming RPC.
///
/// Accepts a stream of Points on a route being traversed, returning a
/// RouteSummary when traversal is completed.
/// </summary>
/// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncClientStreamingCall<global::Routeguide.Point, global::Routeguide.RouteSummary> RecordRoute(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return RecordRoute(new grpc::CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// A client-to-server streaming RPC.
///
/// Accepts a stream of Points on a route being traversed, returning a
/// RouteSummary when traversal is completed.
/// </summary>
/// <param name="options">The options for the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncClientStreamingCall<global::Routeguide.Point, global::Routeguide.RouteSummary> RecordRoute(grpc::CallOptions options)
{
return CallInvoker.AsyncClientStreamingCall(__Method_RecordRoute, null, options);
}
/// <summary>
/// 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).
/// </summary>
/// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncDuplexStreamingCall<global::Routeguide.RouteNote, global::Routeguide.RouteNote> RouteChat(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return RouteChat(new grpc::CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// 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).
/// </summary>
/// <param name="options">The options for the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncDuplexStreamingCall<global::Routeguide.RouteNote, global::Routeguide.RouteNote> RouteChat(grpc::CallOptions options)
{
return CallInvoker.AsyncDuplexStreamingCall(__Method_RouteChat, null, options);
}
/// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
protected override RouteGuideClient NewInstance(ClientBaseConfiguration configuration)
{
return new RouteGuideClient(configuration);
}
} /// <summary>Creates service definition that can be registered with a server</summary>
/// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
public static grpc::ServerServiceDefinition BindService(RouteGuideBase serviceImpl)
{
return grpc::ServerServiceDefinition.CreateBuilder()
.AddMethod(__Method_GetFeature, serviceImpl.GetFeature)
.AddMethod(__Method_ListFeatures, serviceImpl.ListFeatures)
.AddMethod(__Method_RecordRoute, serviceImpl.RecordRoute)
.AddMethod(__Method_RouteChat, serviceImpl.RouteChat).Build();
} /// <summary>Register service method implementations with a service binder. Useful when customizing the service binding logic.
/// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
/// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
/// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
public static void BindService(grpc::ServiceBinderBase serviceBinder, RouteGuideBase serviceImpl)
{
serviceBinder.AddMethod(__Method_GetFeature, serviceImpl.GetFeature);
serviceBinder.AddMethod(__Method_ListFeatures, serviceImpl.ListFeatures);
serviceBinder.AddMethod(__Method_RecordRoute, serviceImpl.RecordRoute);
serviceBinder.AddMethod(__Method_RouteChat, serviceImpl.RouteChat);
} }
}
#endregion
  • 创建服务器
  1. 通过继承从我们的服务定义生成的基类来实现服务功能:执行我们服务的实际“工作”。
  2. 运行gRPC服务器以侦听来自客户端的请求并返回服务响应。
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License. using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks; using Grpc.Core;
using Grpc.Core.Utils; namespace Routeguide
{
/// <summary>
/// Example implementation of RouteGuide server.
/// </summary>
public class RouteGuideImpl : RouteGuide.RouteGuideBase
{
readonly List<Feature> features;
readonly object myLock = new object();
readonly Dictionary<Point, List<RouteNote>> routeNotes = new Dictionary<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 override Task<Feature> GetFeature(Point request, ServerCallContext context)
{
return Task.FromResult(CheckFeature(request));
} /// <summary>
/// Gets all features contained within the given bounding rectangle.
/// </summary>
public override async Task ListFeatures(Rectangle request, IServerStreamWriter<Feature> responseStream, ServerCallContext context)
{
var responses = features.FindAll( (feature) => feature.Exists() && request.Contains(feature.Location) );
foreach (var response in responses)
{
await responseStream.WriteAsync(response);
}
} /// <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 override async Task<RouteSummary> RecordRoute(IAsyncStreamReader<Point> requestStream, ServerCallContext context)
{
int pointCount = ;
int featureCount = ;
int distance = ;
Point previous = null;
var stopwatch = new Stopwatch();
stopwatch.Start(); while (await requestStream.MoveNext())
{
var point = requestStream.Current;
pointCount++;
if (CheckFeature(point).Exists())
{
featureCount++;
}
if (previous != null)
{
distance += (int) previous.GetDistance(point);
}
previous = point;
} stopwatch.Stop(); return new RouteSummary
{
PointCount = pointCount,
FeatureCount = featureCount,
Distance = distance,
ElapsedTime = (int)(stopwatch.ElapsedMilliseconds / )
};
} /// <summary>
/// Receives a stream of message/location pairs, and responds with a stream of all previous
/// messages at each of those locations.
/// </summary>
public override async Task RouteChat(IAsyncStreamReader<RouteNote> requestStream, IServerStreamWriter<RouteNote> responseStream, ServerCallContext context)
{
while (await requestStream.MoveNext())
{
var note = requestStream.Current;
List<RouteNote> prevNotes = AddNoteForLocation(note.Location, note);
foreach (var prevNote in prevNotes)
{
await responseStream.WriteAsync(prevNote);
}
}
} /// <summary>
/// Adds a note for location and returns a list of pre-existing notes for that location (not containing the newly added note).
/// </summary>
private List<RouteNote> AddNoteForLocation(Point location, RouteNote note)
{
lock (myLock)
{
List<RouteNote> notes;
if (!routeNotes.TryGetValue(location, out notes)) {
notes = new List<RouteNote>();
routeNotes.Add(location, notes);
}
var preexistingNotes = new List<RouteNote>(notes);
notes.Add(note);
return preexistingNotes;
}
} /// <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)
{
var result = features.FirstOrDefault((feature) => feature.Location.Equals(location));
if (result == null)
{
// No feature was found, return an unnamed feature.
return new Feature { Name = "", Location = location };
}
return result;
}
}
}
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License. using Grpc.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Routeguide
{
class Program
{
static void Main(string[] args)
{
const int Port = ; var features = RouteGuideUtil.ParseFeatures(RouteGuideUtil.DefaultFeaturesFile); Server server = new Server
{
Services = { RouteGuide.BindService(new RouteGuideImpl(features)) },
Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) }
};
server.Start(); Console.WriteLine("RouteGuide server listening on port " + Port);
Console.WriteLine("Press any key to stop the server...");
Console.ReadKey(); server.ShutdownAsync().Wait();
}
}
}

  如您所见,我们使用Grpc.Core.Server类构建和启动我们的服务器。为此,我们:

  1. 创建一个实例Grpc.Core.Server
  2. 创建我们的服务实现类的实例RouteGuideImpl
  3. 通过将其服务定义添加到Services集合来注册我们的服务实现 (我们从生成的RouteGuide.BindService方法中获取服务定义 )。
  4. 指定我们要用于侦听客户端请求的地址和端口。这是通过添加ServerPortPorts集合来完成的。
  5. 调用Start服务器实例为我们的服务启动RPC服务器。
  •  创建客户端
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License. using Grpc.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Routeguide
{
class Program
{
/// <summary>
/// Sample client code that makes gRPC calls to the server.
/// </summary>
public class RouteGuideClient
{
readonly RouteGuide.RouteGuideClient client; public RouteGuideClient(RouteGuide.RouteGuideClient 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 = new Point { Latitude = lat, Longitude = lon }; Feature feature = client.GetFeature(request);
if (feature.Exists())
{
Log("Found feature called \"{0}\" at {1}, {2}",
feature.Name, feature.Location.GetLatitude(), feature.Location.GetLongitude());
}
else
{
Log("Found no feature at {0}, {1}",
feature.Location.GetLatitude(), feature.Location.GetLongitude());
}
}
catch (RpcException e)
{
Log("RPC failed " + e);
throw;
}
} /// <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 = new Rectangle
{
Lo = new Point { Latitude = lowLat, Longitude = lowLon },
Hi = new Point { Latitude = hiLat, Longitude = hiLon }
}; using (var call = client.ListFeatures(request))
{
var responseStream = call.ResponseStream;
StringBuilder responseLog = new StringBuilder("Result: "); while (await responseStream.MoveNext())
{
Feature feature = responseStream.Current;
responseLog.Append(feature.ToString());
}
Log(responseLog.ToString());
}
}
catch (RpcException e)
{
Log("RPC failed " + e);
throw;
}
} /// <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 = ; i < numPoints; ++i)
{
int index = rand.Next(features.Count);
Point point = features[index].Location;
Log("Visiting point {0}, {1}", point.GetLatitude(), point.GetLongitude()); await call.RequestStream.WriteAsync(point); // A bit of delay before sending the next one.
await Task.Delay(rand.Next() + );
}
await call.RequestStream.CompleteAsync(); RouteSummary summary = await call.ResponseAsync;
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;
}
} /// <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", , ),
NewNote("Second message", , ),
NewNote("Third message", , ),
NewNote("Fourth message", , )
}; 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;
}
} 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 new RouteNote
{
Message = message,
Location = new Point { Latitude = lat, Longitude = lon }
};
}
} static void Main(string[] args)
{
var channel = new Channel("127.0.0.1:50052", ChannelCredentials.Insecure);
var client = new RouteGuideClient(new RouteGuide.RouteGuideClient(channel)); // Looking for a valid feature
client.GetFeature(, -); // Feature missing.
client.GetFeature(, ); // Looking for features between 40, -75 and 42, -73.
client.ListFeatures(, -, , -).Wait(); // Record a few randomly selected points from the features file.
client.RecordRoute(RouteGuideUtil.ParseFeatures(RouteGuideUtil.DefaultFeaturesFile), ).Wait(); // Send and receive some notes.
client.RouteChat().Wait(); channel.ShutdownAsync().Wait();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
}
  • 最后可以在Visual Studio中启动项目RouteGuideClient和RouteGuideServer

在C#中简单使用gRPC的更多相关文章

  1. gRPC初探——概念介绍以及如何构建一个简单的gRPC服务

    目录 引言 1. gRPC简介 2. 使用Protocol Buffers进行服务定义 2.1 定义消息 2.2 定义服务接口 3.构建简单的gRPC服务 3.1 编写proto文件,定义消息和接口 ...

  2. 在浏览器中简单输入一个网址,解密其后发生的一切(http请求的详细过程)

    在浏览器中简单输入一个网址,解密其后发生的一切(http请求的详细过程) 原文链接:http://www.360doc.com/content/14/1117/10/16948208_42571794 ...

  3. win32程序中简单应用mfc

    今日写程序在win32中用CRect发现报错,突然想起来.要引入mfc库.想重新建立一个工程添加对mfc的支持.发现选项不能选.查资料后发现. 在win32程序中简单应用mfc库,只需要简单的引入&l ...

  4. PHP中简单的图形处理

    PHP中简单的图形处理 计应134凌豪 1.加载GD库 GD库是一个开放的动态创建图像.源代码公开的函数库,可以从官方网站http://www.boutell.com/gd处下载.目前,GD库支持GI ...

  5. struts中简单的校验

    Struts中简单的校验 “计应134(实验班) 凌豪” Struts2校验简要说明:struts2中通常情况下,类型转换要在数据校验之前进行.类型转换其实也是基本的服务器端校验,合法数据必然可以通过 ...

  6. .NET平台开源项目速览(20)Newlife.Core中简单灵活的配置文件

    记得5年前开始拼命翻读X组件的源码,特别是XCode,但对Newlife.Core 的东西了解很少,最多只是会用用,而且用到的只是九牛一毛.里面好用的东西太多了. 最近一年时间,零零散散又学了很多,也 ...

  7. [.Net Core] 在 Mvc 中简单使用日志组件

    在 Mvc 中简单使用日志组件 基于 .Net Core 2.0,本文只是蜻蜓点水,并非深入浅出. 目录 使用内置的日志组件 简单过渡到第三方组件 - NLog 使用内置的日志 下面使用控制器 Hom ...

  8. C# Asp.net中简单操作MongoDB数据库(二)

    C# Asp.net中简单操作MongoDB数据库(一)    , mongodb数据库连接可以回顾上面的篇幅. 1.model类: public class BaseEntity { /// < ...

  9. C# Asp.net中简单操作MongoDB数据库(一)

    需要引用MongoDB.Driver.dll.MongoDB.Driver.core.dll.MongoDB.Bson.dll三个dll. 1.数据库连接: public class MongoDb ...

随机推荐

  1. 多线程爬取猫眼电影TOP100并保存到mongo数据库中

    import requests import re import json from requests.exceptions import RequestException from multipro ...

  2. Oracle 三种连接方式 NESTED LOOP HASH JOIN SORT MERGE JOIN

    NESTED LOOP: 对于被连接的数据子集较小的情况,嵌套循环连接是个较好的选择.在嵌套循环中,内表被外表驱动,外表返回的每一行都要在内表中检索找到与它匹配的行,因此整个查询返回的结果集不能太大( ...

  3. learning express step(十一)

    learning express.Router() code: const express = require('express'); const app = express(); var route ...

  4. js快速将字符串数组转化为数字数组(互换)

    1.数字数组转化为字符串数组 var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; arr.map(String); //结果: ['1', '2', '3', '4', '5 ...

  5. 最小生成树&&次小生成树

    对于一个边上具有权值的图来说,其边权值和最小的生成树叫做图G的最小生成树 求无向图最小生成树主要有prim和kruskal两种算法 1.prim 将点集V分成Va和Vb两部分,Va为已经连入生成树的点 ...

  6. 修改quartus 配置rom时memory很小的问题。

    我用的是quartus ii 13版本的仿真软件,在做VGA实验时显示用到640*480的图片所以就需要307200*1bit的rom.但是坑爹的megawizard- plug-in-manager ...

  7. codeforces gym #101161F-Dictionary Game(字典树+树上删边游戏)

    题目链接: http://codeforces.com/gym/101161/attachments 题意: 给一个可以变化的字典树 在字典树上删边 如果某条边和根节点不连通那么这条边也删除 谁没得删 ...

  8. CF1208A

    CF1208A 题意: 就是把斐波那契数列的+改成异或,求第n项的值. 解法: 又是一个人类智慧题,打表找规律. 可以发现答案在 $ a,b,a⊕b $ 三个数中循环 CODE: #include&l ...

  9. Spring框架AOP

    aop技术是面向切面编程思想,作为OOP的延续思想添加到企业开发中,用于弥补OOP开发过程中的缺陷而提出的编程思想.AOP底层也是面向对象:只不过面向的不是普通的Object对象,而是特殊的AOP对象 ...

  10. Java并发指南4:Java中的锁 Lock和synchronized

    Java中的锁机制及Lock类 锁的释放-获取建立的happens before 关系 锁是java并发编程中最重要的同步机制.锁除了让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送消 ...