一、引言

  本文采用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. 爬取淘宝商品数据并保存在excel中

    1.re实现 import requests from requests.exceptions import RequestException import re,json import xlwt,x ...

  2. aspnet_regiis命令使用

    1.使用aspnet_regiis.exe加密web.config文件 http://www.cnblogs.com/MinSentinel/archive/2008/08/01/1258168.ht ...

  3. Java进阶知识18 Spring对象依赖关系的几种写法

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  4. [Luogu] 可持久化线段树 1(主席树)

    https://www.luogu.org/problemnew/show/P3834 #include<cstdio> #include<iostream> #include ...

  5. bbs-admin-自定义admin(二)

    本文内容 目的:模仿admin默认配置,自定义配置类 一 查 1 查看数据 2 查看表头 3 分页器 4 search(搜索框)   5 action(批量处理)    6 filter(分类)   ...

  6. cmake 学习-cmakelists.txt

    #设置库的路径,电脑里有qt4以及qt5,使用qt5时 设置qt5的环境变量(路径). set(CMAKE_PREFIX_PATH $ENV{QTDIR}) #设定工程名称 Project(prona ...

  7. python线程+队列(queue)

    ---恢复内容开始--- python的线程学习 用处 pocpiliang脚本的编写 函数式:调用 _thread 模块中的start_new_thread()函数来产生新线程.语法如下: _thr ...

  8. Linux设备驱动程序 之 中断

    中断 中断使得硬件可以发出通知给处理器,本质上是一种特殊的电信号,由硬件设备发向处理器,处理器接收到中断后,会马上向操作系统反应此信号的到来,然后就由操作系统负责处理这些新来的数据:硬件设备生成中断并 ...

  9. 如何丧心病狂的使用python爬虫读小说

    写在前边 其实一直想入门python很久了,慕课网啊,菜鸟教程啊python的基础的知识被我翻了很多遍了,但是一直没有什么实践.刚好,这两天被别人一直安利一本小说<我可能修的是假仙>,还在 ...

  10. kotlin 泛型中类型投射

    fun main(arg: Array<String>) { var ints:Array<Int> = arrayOf(, , ) val any =Array<Any ...