grpc 实例

官网

https://github.com/grpc/grpc

下载源码

以官方示例route_guide为例

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 {

  // 一个 简单 RPC , 客户端使用存根发送请求到服务器并等待响应返回,就像平常的函数调用一样。
  rpc GetFeature(Point) returns (Feature) {}

  // 一个 服务器端流式 RPC , 客户端发送请求到服务器,拿到一个流去读取返回的消息序列。 客户端读取返回的	流,直到里面没有任何消息。从例子中可以看出,通过在响应类型前插入 stream 关键字,可以指定一个服务器     端的流方法
  rpc ListFeatures(Rectangle) returns (stream Feature) {}

  //一个 客户端流式 RPC , 客户端写入一个消息序列并将其发送到服务器,同样也是使用流。一旦客户端完成写入消息,它等待服务器完成读取返回它的响应。通过在 请求 类型前指定 stream 关键字来指定一个客户端的流方法
  rpc RecordRoute(stream Point) returns (RouteSummary) {}

  // 一个 双向流式 RPC 是双方使用读写流去发送一个消息序列。两个流独立操作,因此客户端和服务器可以以任意喜欢的顺序读写:比如, 服务器可以在写入响应前等待接收所有的客户端消息,或者可以交替的读取和写入消息,或者其他读写的组合。 每个流中的消息顺序被预留。你可以通过在请求和响应前加 stream 关键字去制定方法的类型
  rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}

//下面是消息类型定义以及在服务方法中使用的响应类型

// Points are represented as latitude-longitude pairs in the E7 representation
// (degrees multiplied by 10**7 and rounded to the nearest integer).
// Latitudes should be in the range +/- 90 degrees and longitude should be in
// the range +/- 180 degrees (inclusive).
message Point {
  int32 latitude = 1;
  int32 longitude = 2;
}

// A latitude-longitude rectangle, represented as two diagonally opposite
// points "lo" and "hi".
message Rectangle {
  // One corner of the rectangle.
  Point lo = 1;

  // The other corner of the rectangle.
  Point hi = 2;
}

// A feature names something at a given point.
//
// If a feature could not be named, the name is empty.
message Feature {
  // The name of the feature.
  string name = 1;

  // The point where the feature is detected.
  Point location = 2;
}

// A RouteNote is a message sent while at a given point.
message RouteNote {
  // The location from which the message is sent.
  Point location = 1;

  // The message to be sent.
  string message = 2;
}

// A RouteSummary is received in response to a RecordRoute rpc.
//
// It contains the number of individual points received, the number of
// detected features, and the total distance covered as the cumulative sum of
// the distance between each point.
message RouteSummary {
  // The number of points received.
  int32 point_count = 1;

  // The number of known features passed while traversing the route.
  int32 feature_count = 2;

  // The distance covered in metres.
  int32 distance = 3;

  // The duration of the traversal in seconds.
  int32 elapsed_time = 4;
}

C++

生成代码

安装protoc grpc

  • sudo apt install protobuf-compiler
  • apt install protobuf-compiler-grpc

生成代码:

protoc -I . --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` route_guide.proto

protoc -I . --cpp_out=. route_guide.proto

生成如下四个文件:

  • route_guide.pb.h, 声明生成的消息类的头文件
  • route_guide.pb.cc, 包含消息类的实现
  • route_guide.grpc.pb.h, 声明你生成的服务类的头文件
  • route_guide.grpc.pb.cc, 包含服务类的实现
route_guide.pb.h
// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: route_guide.proto

#ifndef PROTOBUF_route_5fguide_2eproto__INCLUDED
#define PROTOBUF_route_5fguide_2eproto__INCLUDED

#include <string>

#include <google/protobuf/stubs/common.h>

#if GOOGLE_PROTOBUF_VERSION < 3000000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers.  Please update
#error your headers.
#endif
#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers.  Please
#error regenerate this file with a newer version of protoc.
#endif

#include <google/protobuf/arena.h>
#include <google/protobuf/arenastring.h>
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/metadata.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/unknown_field_set.h>
// @@protoc_insertion_point(includes)

namespace routeguide {

// Internal implementation detail -- do not call these.
void protobuf_AddDesc_route_5fguide_2eproto();
void protobuf_AssignDesc_route_5fguide_2eproto();
void protobuf_ShutdownFile_route_5fguide_2eproto();

class Feature;
class Point;
class Rectangle;
class RouteNote;
class RouteSummary;

// ===================================================================

class Point : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:routeguide.Point) */ {
 public:
  Point();
  virtual ~Point();

  Point(const Point& from);

  inline Point& operator=(const Point& from) {
    CopyFrom(from);
    return *this;
  }

  static const ::google::protobuf::Descriptor* descriptor();
  static const Point& default_instance();

  void Swap(Point* other);

  // implements Message ----------------------------------------------

  inline Point* New() const { return New(NULL); }

  Point* New(::google::protobuf::Arena* arena) const;
  void CopyFrom(const ::google::protobuf::Message& from);
  void MergeFrom(const ::google::protobuf::Message& from);
  void CopyFrom(const Point& from);
  void MergeFrom(const Point& from);
  void Clear();
  bool IsInitialized() const;

  int ByteSize() const;
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input);
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const;
  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
      bool deterministic, ::google::protobuf::uint8* output) const;
  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
    return InternalSerializeWithCachedSizesToArray(false, output);
  }
  int GetCachedSize() const { return _cached_size_; }
  private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const;
  void InternalSwap(Point* other);
  private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return _internal_metadata_.arena();
  }
  inline void* MaybeArenaPtr() const {
    return _internal_metadata_.raw_arena_ptr();
  }
  public:

  ::google::protobuf::Metadata GetMetadata() const;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // optional int32 latitude = 1;
  void clear_latitude();
  static const int kLatitudeFieldNumber = 1;
  ::google::protobuf::int32 latitude() const;
  void set_latitude(::google::protobuf::int32 value);

  // optional int32 longitude = 2;
  void clear_longitude();
  static const int kLongitudeFieldNumber = 2;
  ::google::protobuf::int32 longitude() const;
  void set_longitude(::google::protobuf::int32 value);

  // @@protoc_insertion_point(class_scope:routeguide.Point)
 private:

  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
  bool _is_default_instance_;
  ::google::protobuf::int32 latitude_;
  ::google::protobuf::int32 longitude_;
  mutable int _cached_size_;
  friend void  protobuf_AddDesc_route_5fguide_2eproto();
  friend void protobuf_AssignDesc_route_5fguide_2eproto();
  friend void protobuf_ShutdownFile_route_5fguide_2eproto();

  void InitAsDefaultInstance();
  static Point* default_instance_;
};
// -------------------------------------------------------------------

class Rectangle : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:routeguide.Rectangle) */ {
 public:
  Rectangle();
  virtual ~Rectangle();

  Rectangle(const Rectangle& from);

  inline Rectangle& operator=(const Rectangle& from) {
    CopyFrom(from);
    return *this;
  }

  static const ::google::protobuf::Descriptor* descriptor();
  static const Rectangle& default_instance();

  void Swap(Rectangle* other);

  // implements Message ----------------------------------------------

  inline Rectangle* New() const { return New(NULL); }

  Rectangle* New(::google::protobuf::Arena* arena) const;
  void CopyFrom(const ::google::protobuf::Message& from);
  void MergeFrom(const ::google::protobuf::Message& from);
  void CopyFrom(const Rectangle& from);
  void MergeFrom(const Rectangle& from);
  void Clear();
  bool IsInitialized() const;

  int ByteSize() const;
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input);
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const;
  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
      bool deterministic, ::google::protobuf::uint8* output) const;
  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
    return InternalSerializeWithCachedSizesToArray(false, output);
  }
  int GetCachedSize() const { return _cached_size_; }
  private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const;
  void InternalSwap(Rectangle* other);
  private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return _internal_metadata_.arena();
  }
  inline void* MaybeArenaPtr() const {
    return _internal_metadata_.raw_arena_ptr();
  }
  public:

  ::google::protobuf::Metadata GetMetadata() const;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // optional .routeguide.Point lo = 1;
  bool has_lo() const;
  void clear_lo();
  static const int kLoFieldNumber = 1;
  const ::routeguide::Point& lo() const;
  ::routeguide::Point* mutable_lo();
  ::routeguide::Point* release_lo();
  void set_allocated_lo(::routeguide::Point* lo);

  // optional .routeguide.Point hi = 2;
  bool has_hi() const;
  void clear_hi();
  static const int kHiFieldNumber = 2;
  const ::routeguide::Point& hi() const;
  ::routeguide::Point* mutable_hi();
  ::routeguide::Point* release_hi();
  void set_allocated_hi(::routeguide::Point* hi);

  // @@protoc_insertion_point(class_scope:routeguide.Rectangle)
 private:

  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
  bool _is_default_instance_;
  ::routeguide::Point* lo_;
  ::routeguide::Point* hi_;
  mutable int _cached_size_;
  friend void  protobuf_AddDesc_route_5fguide_2eproto();
  friend void protobuf_AssignDesc_route_5fguide_2eproto();
  friend void protobuf_ShutdownFile_route_5fguide_2eproto();

  void InitAsDefaultInstance();
  static Rectangle* default_instance_;
};
// -------------------------------------------------------------------

class Feature : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:routeguide.Feature) */ {
 public:
  Feature();
  virtual ~Feature();

  Feature(const Feature& from);

  inline Feature& operator=(const Feature& from) {
    CopyFrom(from);
    return *this;
  }

  static const ::google::protobuf::Descriptor* descriptor();
  static const Feature& default_instance();

  void Swap(Feature* other);

  // implements Message ----------------------------------------------

  inline Feature* New() const { return New(NULL); }

  Feature* New(::google::protobuf::Arena* arena) const;
  void CopyFrom(const ::google::protobuf::Message& from);
  void MergeFrom(const ::google::protobuf::Message& from);
  void CopyFrom(const Feature& from);
  void MergeFrom(const Feature& from);
  void Clear();
  bool IsInitialized() const;

  int ByteSize() const;
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input);
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const;
  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
      bool deterministic, ::google::protobuf::uint8* output) const;
  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
    return InternalSerializeWithCachedSizesToArray(false, output);
  }
  int GetCachedSize() const { return _cached_size_; }
  private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const;
  void InternalSwap(Feature* other);
  private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return _internal_metadata_.arena();
  }
  inline void* MaybeArenaPtr() const {
    return _internal_metadata_.raw_arena_ptr();
  }
  public:

  ::google::protobuf::Metadata GetMetadata() const;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // optional string name = 1;
  void clear_name();
  static const int kNameFieldNumber = 1;
  const ::std::string& name() const;
  void set_name(const ::std::string& value);
  void set_name(const char* value);
  void set_name(const char* value, size_t size);
  ::std::string* mutable_name();
  ::std::string* release_name();
  void set_allocated_name(::std::string* name);

  // optional .routeguide.Point location = 2;
  bool has_location() const;
  void clear_location();
  static const int kLocationFieldNumber = 2;
  const ::routeguide::Point& location() const;
  ::routeguide::Point* mutable_location();
  ::routeguide::Point* release_location();
  void set_allocated_location(::routeguide::Point* location);

  // @@protoc_insertion_point(class_scope:routeguide.Feature)
 private:

  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
  bool _is_default_instance_;
  ::google::protobuf::internal::ArenaStringPtr name_;
  ::routeguide::Point* location_;
  mutable int _cached_size_;
  friend void  protobuf_AddDesc_route_5fguide_2eproto();
  friend void protobuf_AssignDesc_route_5fguide_2eproto();
  friend void protobuf_ShutdownFile_route_5fguide_2eproto();

  void InitAsDefaultInstance();
  static Feature* default_instance_;
};
// -------------------------------------------------------------------

class RouteNote : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:routeguide.RouteNote) */ {
 public:
  RouteNote();
  virtual ~RouteNote();

  RouteNote(const RouteNote& from);

  inline RouteNote& operator=(const RouteNote& from) {
    CopyFrom(from);
    return *this;
  }

  static const ::google::protobuf::Descriptor* descriptor();
  static const RouteNote& default_instance();

  void Swap(RouteNote* other);

  // implements Message ----------------------------------------------

  inline RouteNote* New() const { return New(NULL); }

  RouteNote* New(::google::protobuf::Arena* arena) const;
  void CopyFrom(const ::google::protobuf::Message& from);
  void MergeFrom(const ::google::protobuf::Message& from);
  void CopyFrom(const RouteNote& from);
  void MergeFrom(const RouteNote& from);
  void Clear();
  bool IsInitialized() const;

  int ByteSize() const;
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input);
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const;
  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
      bool deterministic, ::google::protobuf::uint8* output) const;
  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
    return InternalSerializeWithCachedSizesToArray(false, output);
  }
  int GetCachedSize() const { return _cached_size_; }
  private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const;
  void InternalSwap(RouteNote* other);
  private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return _internal_metadata_.arena();
  }
  inline void* MaybeArenaPtr() const {
    return _internal_metadata_.raw_arena_ptr();
  }
  public:

  ::google::protobuf::Metadata GetMetadata() const;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // optional .routeguide.Point location = 1;
  bool has_location() const;
  void clear_location();
  static const int kLocationFieldNumber = 1;
  const ::routeguide::Point& location() const;
  ::routeguide::Point* mutable_location();
  ::routeguide::Point* release_location();
  void set_allocated_location(::routeguide::Point* location);

  // optional string message = 2;
  void clear_message();
  static const int kMessageFieldNumber = 2;
  const ::std::string& message() const;
  void set_message(const ::std::string& value);
  void set_message(const char* value);
  void set_message(const char* value, size_t size);
  ::std::string* mutable_message();
  ::std::string* release_message();
  void set_allocated_message(::std::string* message);

  // @@protoc_insertion_point(class_scope:routeguide.RouteNote)
 private:

  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
  bool _is_default_instance_;
  ::routeguide::Point* location_;
  ::google::protobuf::internal::ArenaStringPtr message_;
  mutable int _cached_size_;
  friend void  protobuf_AddDesc_route_5fguide_2eproto();
  friend void protobuf_AssignDesc_route_5fguide_2eproto();
  friend void protobuf_ShutdownFile_route_5fguide_2eproto();

  void InitAsDefaultInstance();
  static RouteNote* default_instance_;
};
// -------------------------------------------------------------------

class RouteSummary : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:routeguide.RouteSummary) */ {
 public:
  RouteSummary();
  virtual ~RouteSummary();

  RouteSummary(const RouteSummary& from);

  inline RouteSummary& operator=(const RouteSummary& from) {
    CopyFrom(from);
    return *this;
  }

  static const ::google::protobuf::Descriptor* descriptor();
  static const RouteSummary& default_instance();

  void Swap(RouteSummary* other);

  // implements Message ----------------------------------------------

  inline RouteSummary* New() const { return New(NULL); }

  RouteSummary* New(::google::protobuf::Arena* arena) const;
  void CopyFrom(const ::google::protobuf::Message& from);
  void MergeFrom(const ::google::protobuf::Message& from);
  void CopyFrom(const RouteSummary& from);
  void MergeFrom(const RouteSummary& from);
  void Clear();
  bool IsInitialized() const;

  int ByteSize() const;
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input);
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const;
  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
      bool deterministic, ::google::protobuf::uint8* output) const;
  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
    return InternalSerializeWithCachedSizesToArray(false, output);
  }
  int GetCachedSize() const { return _cached_size_; }
  private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const;
  void InternalSwap(RouteSummary* other);
  private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return _internal_metadata_.arena();
  }
  inline void* MaybeArenaPtr() const {
    return _internal_metadata_.raw_arena_ptr();
  }
  public:

  ::google::protobuf::Metadata GetMetadata() const;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // optional int32 point_count = 1;
  void clear_point_count();
  static const int kPointCountFieldNumber = 1;
  ::google::protobuf::int32 point_count() const;
  void set_point_count(::google::protobuf::int32 value);

  // optional int32 feature_count = 2;
  void clear_feature_count();
  static const int kFeatureCountFieldNumber = 2;
  ::google::protobuf::int32 feature_count() const;
  void set_feature_count(::google::protobuf::int32 value);

  // optional int32 distance = 3;
  void clear_distance();
  static const int kDistanceFieldNumber = 3;
  ::google::protobuf::int32 distance() const;
  void set_distance(::google::protobuf::int32 value);

  // optional int32 elapsed_time = 4;
  void clear_elapsed_time();
  static const int kElapsedTimeFieldNumber = 4;
  ::google::protobuf::int32 elapsed_time() const;
  void set_elapsed_time(::google::protobuf::int32 value);

  // @@protoc_insertion_point(class_scope:routeguide.RouteSummary)
 private:

  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
  bool _is_default_instance_;
  ::google::protobuf::int32 point_count_;
  ::google::protobuf::int32 feature_count_;
  ::google::protobuf::int32 distance_;
  ::google::protobuf::int32 elapsed_time_;
  mutable int _cached_size_;
  friend void  protobuf_AddDesc_route_5fguide_2eproto();
  friend void protobuf_AssignDesc_route_5fguide_2eproto();
  friend void protobuf_ShutdownFile_route_5fguide_2eproto();

  void InitAsDefaultInstance();
  static RouteSummary* default_instance_;
};
// ===================================================================


// ===================================================================

#if !PROTOBUF_INLINE_NOT_IN_HEADERS
// Point

// optional int32 latitude = 1;
inline void Point::clear_latitude() {
  latitude_ = 0;
}
inline ::google::protobuf::int32 Point::latitude() const {
  // @@protoc_insertion_point(field_get:routeguide.Point.latitude)
  return latitude_;
}
inline void Point::set_latitude(::google::protobuf::int32 value) {
  
  latitude_ = value;
  // @@protoc_insertion_point(field_set:routeguide.Point.latitude)
}

// optional int32 longitude = 2;
inline void Point::clear_longitude() {
  longitude_ = 0;
}
inline ::google::protobuf::int32 Point::longitude() const {
  // @@protoc_insertion_point(field_get:routeguide.Point.longitude)
  return longitude_;
}
inline void Point::set_longitude(::google::protobuf::int32 value) {
  
  longitude_ = value;
  // @@protoc_insertion_point(field_set:routeguide.Point.longitude)
}

// -------------------------------------------------------------------

// Rectangle

// optional .routeguide.Point lo = 1;
inline bool Rectangle::has_lo() const {
  return !_is_default_instance_ && lo_ != NULL;
}
inline void Rectangle::clear_lo() {
  if (GetArenaNoVirtual() == NULL && lo_ != NULL) delete lo_;
  lo_ = NULL;
}
inline const ::routeguide::Point& Rectangle::lo() const {
  // @@protoc_insertion_point(field_get:routeguide.Rectangle.lo)
  return lo_ != NULL ? *lo_ : *default_instance_->lo_;
}
inline ::routeguide::Point* Rectangle::mutable_lo() {
  
  if (lo_ == NULL) {
    lo_ = new ::routeguide::Point;
  }
  // @@protoc_insertion_point(field_mutable:routeguide.Rectangle.lo)
  return lo_;
}
inline ::routeguide::Point* Rectangle::release_lo() {
  // @@protoc_insertion_point(field_release:routeguide.Rectangle.lo)
  
  ::routeguide::Point* temp = lo_;
  lo_ = NULL;
  return temp;
}
inline void Rectangle::set_allocated_lo(::routeguide::Point* lo) {
  delete lo_;
  lo_ = lo;
  if (lo) {
    
  } else {
    
  }
  // @@protoc_insertion_point(field_set_allocated:routeguide.Rectangle.lo)
}

// optional .routeguide.Point hi = 2;
inline bool Rectangle::has_hi() const {
  return !_is_default_instance_ && hi_ != NULL;
}
inline void Rectangle::clear_hi() {
  if (GetArenaNoVirtual() == NULL && hi_ != NULL) delete hi_;
  hi_ = NULL;
}
inline const ::routeguide::Point& Rectangle::hi() const {
  // @@protoc_insertion_point(field_get:routeguide.Rectangle.hi)
  return hi_ != NULL ? *hi_ : *default_instance_->hi_;
}
inline ::routeguide::Point* Rectangle::mutable_hi() {
  
  if (hi_ == NULL) {
    hi_ = new ::routeguide::Point;
  }
  // @@protoc_insertion_point(field_mutable:routeguide.Rectangle.hi)
  return hi_;
}
inline ::routeguide::Point* Rectangle::release_hi() {
  // @@protoc_insertion_point(field_release:routeguide.Rectangle.hi)
  
  ::routeguide::Point* temp = hi_;
  hi_ = NULL;
  return temp;
}
inline void Rectangle::set_allocated_hi(::routeguide::Point* hi) {
  delete hi_;
  hi_ = hi;
  if (hi) {
    
  } else {
    
  }
  // @@protoc_insertion_point(field_set_allocated:routeguide.Rectangle.hi)
}

// -------------------------------------------------------------------

// Feature

// optional string name = 1;
inline void Feature::clear_name() {
  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& Feature::name() const {
  // @@protoc_insertion_point(field_get:routeguide.Feature.name)
  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void Feature::set_name(const ::std::string& value) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:routeguide.Feature.name)
}
inline void Feature::set_name(const char* value) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:routeguide.Feature.name)
}
inline void Feature::set_name(const char* value, size_t size) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:routeguide.Feature.name)
}
inline ::std::string* Feature::mutable_name() {
  
  // @@protoc_insertion_point(field_mutable:routeguide.Feature.name)
  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Feature::release_name() {
  // @@protoc_insertion_point(field_release:routeguide.Feature.name)
  
  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void Feature::set_allocated_name(::std::string* name) {
  if (name != NULL) {
    
  } else {
    
  }
  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
  // @@protoc_insertion_point(field_set_allocated:routeguide.Feature.name)
}

// optional .routeguide.Point location = 2;
inline bool Feature::has_location() const {
  return !_is_default_instance_ && location_ != NULL;
}
inline void Feature::clear_location() {
  if (GetArenaNoVirtual() == NULL && location_ != NULL) delete location_;
  location_ = NULL;
}
inline const ::routeguide::Point& Feature::location() const {
  // @@protoc_insertion_point(field_get:routeguide.Feature.location)
  return location_ != NULL ? *location_ : *default_instance_->location_;
}
inline ::routeguide::Point* Feature::mutable_location() {
  
  if (location_ == NULL) {
    location_ = new ::routeguide::Point;
  }
  // @@protoc_insertion_point(field_mutable:routeguide.Feature.location)
  return location_;
}
inline ::routeguide::Point* Feature::release_location() {
  // @@protoc_insertion_point(field_release:routeguide.Feature.location)
  
  ::routeguide::Point* temp = location_;
  location_ = NULL;
  return temp;
}
inline void Feature::set_allocated_location(::routeguide::Point* location) {
  delete location_;
  location_ = location;
  if (location) {
    
  } else {
    
  }
  // @@protoc_insertion_point(field_set_allocated:routeguide.Feature.location)
}

// -------------------------------------------------------------------

// RouteNote

// optional .routeguide.Point location = 1;
inline bool RouteNote::has_location() const {
  return !_is_default_instance_ && location_ != NULL;
}
inline void RouteNote::clear_location() {
  if (GetArenaNoVirtual() == NULL && location_ != NULL) delete location_;
  location_ = NULL;
}
inline const ::routeguide::Point& RouteNote::location() const {
  // @@protoc_insertion_point(field_get:routeguide.RouteNote.location)
  return location_ != NULL ? *location_ : *default_instance_->location_;
}
inline ::routeguide::Point* RouteNote::mutable_location() {
  
  if (location_ == NULL) {
    location_ = new ::routeguide::Point;
  }
  // @@protoc_insertion_point(field_mutable:routeguide.RouteNote.location)
  return location_;
}
inline ::routeguide::Point* RouteNote::release_location() {
  // @@protoc_insertion_point(field_release:routeguide.RouteNote.location)
  
  ::routeguide::Point* temp = location_;
  location_ = NULL;
  return temp;
}
inline void RouteNote::set_allocated_location(::routeguide::Point* location) {
  delete location_;
  location_ = location;
  if (location) {
    
  } else {
    
  }
  // @@protoc_insertion_point(field_set_allocated:routeguide.RouteNote.location)
}

// optional string message = 2;
inline void RouteNote::clear_message() {
  message_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& RouteNote::message() const {
  // @@protoc_insertion_point(field_get:routeguide.RouteNote.message)
  return message_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void RouteNote::set_message(const ::std::string& value) {
  
  message_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:routeguide.RouteNote.message)
}
inline void RouteNote::set_message(const char* value) {
  
  message_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:routeguide.RouteNote.message)
}
inline void RouteNote::set_message(const char* value, size_t size) {
  
  message_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:routeguide.RouteNote.message)
}
inline ::std::string* RouteNote::mutable_message() {
  
  // @@protoc_insertion_point(field_mutable:routeguide.RouteNote.message)
  return message_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* RouteNote::release_message() {
  // @@protoc_insertion_point(field_release:routeguide.RouteNote.message)
  
  return message_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void RouteNote::set_allocated_message(::std::string* message) {
  if (message != NULL) {
    
  } else {
    
  }
  message_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), message);
  // @@protoc_insertion_point(field_set_allocated:routeguide.RouteNote.message)
}

// -------------------------------------------------------------------

// RouteSummary

// optional int32 point_count = 1;
inline void RouteSummary::clear_point_count() {
  point_count_ = 0;
}
inline ::google::protobuf::int32 RouteSummary::point_count() const {
  // @@protoc_insertion_point(field_get:routeguide.RouteSummary.point_count)
  return point_count_;
}
inline void RouteSummary::set_point_count(::google::protobuf::int32 value) {
  
  point_count_ = value;
  // @@protoc_insertion_point(field_set:routeguide.RouteSummary.point_count)
}

// optional int32 feature_count = 2;
inline void RouteSummary::clear_feature_count() {
  feature_count_ = 0;
}
inline ::google::protobuf::int32 RouteSummary::feature_count() const {
  // @@protoc_insertion_point(field_get:routeguide.RouteSummary.feature_count)
  return feature_count_;
}
inline void RouteSummary::set_feature_count(::google::protobuf::int32 value) {
  
  feature_count_ = value;
  // @@protoc_insertion_point(field_set:routeguide.RouteSummary.feature_count)
}

// optional int32 distance = 3;
inline void RouteSummary::clear_distance() {
  distance_ = 0;
}
inline ::google::protobuf::int32 RouteSummary::distance() const {
  // @@protoc_insertion_point(field_get:routeguide.RouteSummary.distance)
  return distance_;
}
inline void RouteSummary::set_distance(::google::protobuf::int32 value) {
  
  distance_ = value;
  // @@protoc_insertion_point(field_set:routeguide.RouteSummary.distance)
}

// optional int32 elapsed_time = 4;
inline void RouteSummary::clear_elapsed_time() {
  elapsed_time_ = 0;
}
inline ::google::protobuf::int32 RouteSummary::elapsed_time() const {
  // @@protoc_insertion_point(field_get:routeguide.RouteSummary.elapsed_time)
  return elapsed_time_;
}
inline void RouteSummary::set_elapsed_time(::google::protobuf::int32 value) {
  
  elapsed_time_ = value;
  // @@protoc_insertion_point(field_set:routeguide.RouteSummary.elapsed_time)
}

#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
// -------------------------------------------------------------------

// -------------------------------------------------------------------

// -------------------------------------------------------------------

// -------------------------------------------------------------------


// @@protoc_insertion_point(namespace_scope)

}  // namespace routeguide

// @@protoc_insertion_point(global_scope)

#endif  // PROTOBUF_route_5fguide_2eproto__INCLUDED

route_guide.pb.cc
// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: route_guide.proto

#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
#include "route_guide.pb.h"

#include <algorithm>

#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/port.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/wire_format.h>
// @@protoc_insertion_point(includes)

namespace routeguide {

namespace {

const ::google::protobuf::Descriptor* Point_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
  Point_reflection_ = NULL;
const ::google::protobuf::Descriptor* Rectangle_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
  Rectangle_reflection_ = NULL;
const ::google::protobuf::Descriptor* Feature_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
  Feature_reflection_ = NULL;
const ::google::protobuf::Descriptor* RouteNote_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
  RouteNote_reflection_ = NULL;
const ::google::protobuf::Descriptor* RouteSummary_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
  RouteSummary_reflection_ = NULL;

}  // namespace


void protobuf_AssignDesc_route_5fguide_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AssignDesc_route_5fguide_2eproto() {
  protobuf_AddDesc_route_5fguide_2eproto();
  const ::google::protobuf::FileDescriptor* file =
    ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
      "route_guide.proto");
  GOOGLE_CHECK(file != NULL);
  Point_descriptor_ = file->message_type(0);
  static const int Point_offsets_[2] = {
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Point, latitude_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Point, longitude_),
  };
  Point_reflection_ =
    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
      Point_descriptor_,
      Point::default_instance_,
      Point_offsets_,
      -1,
      -1,
      -1,
      sizeof(Point),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Point, _internal_metadata_),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Point, _is_default_instance_));
  Rectangle_descriptor_ = file->message_type(1);
  static const int Rectangle_offsets_[2] = {
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Rectangle, lo_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Rectangle, hi_),
  };
  Rectangle_reflection_ =
    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
      Rectangle_descriptor_,
      Rectangle::default_instance_,
      Rectangle_offsets_,
      -1,
      -1,
      -1,
      sizeof(Rectangle),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Rectangle, _internal_metadata_),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Rectangle, _is_default_instance_));
  Feature_descriptor_ = file->message_type(2);
  static const int Feature_offsets_[2] = {
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Feature, name_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Feature, location_),
  };
  Feature_reflection_ =
    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
      Feature_descriptor_,
      Feature::default_instance_,
      Feature_offsets_,
      -1,
      -1,
      -1,
      sizeof(Feature),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Feature, _internal_metadata_),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Feature, _is_default_instance_));
  RouteNote_descriptor_ = file->message_type(3);
  static const int RouteNote_offsets_[2] = {
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RouteNote, location_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RouteNote, message_),
  };
  RouteNote_reflection_ =
    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
      RouteNote_descriptor_,
      RouteNote::default_instance_,
      RouteNote_offsets_,
      -1,
      -1,
      -1,
      sizeof(RouteNote),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RouteNote, _internal_metadata_),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RouteNote, _is_default_instance_));
  RouteSummary_descriptor_ = file->message_type(4);
  static const int RouteSummary_offsets_[4] = {
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RouteSummary, point_count_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RouteSummary, feature_count_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RouteSummary, distance_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RouteSummary, elapsed_time_),
  };
  RouteSummary_reflection_ =
    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
      RouteSummary_descriptor_,
      RouteSummary::default_instance_,
      RouteSummary_offsets_,
      -1,
      -1,
      -1,
      sizeof(RouteSummary),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RouteSummary, _internal_metadata_),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(RouteSummary, _is_default_instance_));
}

namespace {

GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
inline void protobuf_AssignDescriptorsOnce() {
  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
                 &protobuf_AssignDesc_route_5fguide_2eproto);
}

void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
void protobuf_RegisterTypes(const ::std::string&) {
  protobuf_AssignDescriptorsOnce();
  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
      Point_descriptor_, &Point::default_instance());
  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
      Rectangle_descriptor_, &Rectangle::default_instance());
  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
      Feature_descriptor_, &Feature::default_instance());
  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
      RouteNote_descriptor_, &RouteNote::default_instance());
  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
      RouteSummary_descriptor_, &RouteSummary::default_instance());
}

}  // namespace

void protobuf_ShutdownFile_route_5fguide_2eproto() {
  delete Point::default_instance_;
  delete Point_reflection_;
  delete Rectangle::default_instance_;
  delete Rectangle_reflection_;
  delete Feature::default_instance_;
  delete Feature_reflection_;
  delete RouteNote::default_instance_;
  delete RouteNote_reflection_;
  delete RouteSummary::default_instance_;
  delete RouteSummary_reflection_;
}

void protobuf_AddDesc_route_5fguide_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AddDesc_route_5fguide_2eproto() {
  static bool already_here = false;
  if (already_here) return;
  already_here = true;
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
    "\n\021route_guide.proto\022\nrouteguide\",\n\005Point"
    "\022\020\n\010latitude\030\001 \001(\005\022\021\n\tlongitude\030\002 \001(\005\"I\n"
    "\tRectangle\022\035\n\002lo\030\001 \001(\0132\021.routeguide.Poin"
    "t\022\035\n\002hi\030\002 \001(\0132\021.routeguide.Point\"<\n\007Feat"
    "ure\022\014\n\004name\030\001 \001(\t\022#\n\010location\030\002 \001(\0132\021.ro"
    "uteguide.Point\"A\n\tRouteNote\022#\n\010location\030"
    "\001 \001(\0132\021.routeguide.Point\022\017\n\007message\030\002 \001("
    "\t\"b\n\014RouteSummary\022\023\n\013point_count\030\001 \001(\005\022\025"
    "\n\rfeature_count\030\002 \001(\005\022\020\n\010distance\030\003 \001(\005\022"
    "\024\n\014elapsed_time\030\004 \001(\0052\205\002\n\nRouteGuide\0226\n\n"
    "GetFeature\022\021.routeguide.Point\032\023.routegui"
    "de.Feature\"\000\022>\n\014ListFeatures\022\025.routeguid"
    "e.Rectangle\032\023.routeguide.Feature\"\0000\001\022>\n\013"
    "RecordRoute\022\021.routeguide.Point\032\030.routegu"
    "ide.RouteSummary\"\000(\001\022\?\n\tRouteChat\022\025.rout"
    "eguide.RouteNote\032\025.routeguide.RouteNote\""
    "\000(\0010\001B6\n\033io.grpc.examples.routeguideB\017Ro"
    "uteGuideProtoP\001\242\002\003RTGb\006proto3", 709);
  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
    "route_guide.proto", &protobuf_RegisterTypes);
  Point::default_instance_ = new Point();
  Rectangle::default_instance_ = new Rectangle();
  Feature::default_instance_ = new Feature();
  RouteNote::default_instance_ = new RouteNote();
  RouteSummary::default_instance_ = new RouteSummary();
  Point::default_instance_->InitAsDefaultInstance();
  Rectangle::default_instance_->InitAsDefaultInstance();
  Feature::default_instance_->InitAsDefaultInstance();
  RouteNote::default_instance_->InitAsDefaultInstance();
  RouteSummary::default_instance_->InitAsDefaultInstance();
  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_route_5fguide_2eproto);
}

// Force AddDescriptors() to be called at static initialization time.
struct StaticDescriptorInitializer_route_5fguide_2eproto {
  StaticDescriptorInitializer_route_5fguide_2eproto() {
    protobuf_AddDesc_route_5fguide_2eproto();
  }
} static_descriptor_initializer_route_5fguide_2eproto_;

// ===================================================================

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int Point::kLatitudeFieldNumber;
const int Point::kLongitudeFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

Point::Point()
  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:routeguide.Point)
}

void Point::InitAsDefaultInstance() {
  _is_default_instance_ = true;
}

Point::Point(const Point& from)
  : ::google::protobuf::Message(),
    _internal_metadata_(NULL) {
  SharedCtor();
  MergeFrom(from);
  // @@protoc_insertion_point(copy_constructor:routeguide.Point)
}

void Point::SharedCtor() {
    _is_default_instance_ = false;
  _cached_size_ = 0;
  latitude_ = 0;
  longitude_ = 0;
}

Point::~Point() {
  // @@protoc_insertion_point(destructor:routeguide.Point)
  SharedDtor();
}

void Point::SharedDtor() {
  if (this != default_instance_) {
  }
}

void Point::SetCachedSize(int size) const {
  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* Point::descriptor() {
  protobuf_AssignDescriptorsOnce();
  return Point_descriptor_;
}

const Point& Point::default_instance() {
  if (default_instance_ == NULL) protobuf_AddDesc_route_5fguide_2eproto();
  return *default_instance_;
}

Point* Point::default_instance_ = NULL;

Point* Point::New(::google::protobuf::Arena* arena) const {
  Point* n = new Point;
  if (arena != NULL) {
    arena->Own(n);
  }
  return n;
}

void Point::Clear() {
// @@protoc_insertion_point(message_clear_start:routeguide.Point)
#if defined(__clang__)
#define ZR_HELPER_(f) \
  _Pragma("clang diagnostic push") \
  _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
  __builtin_offsetof(Point, f) \
  _Pragma("clang diagnostic pop")
#else
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
  &reinterpret_cast<Point*>(16)->f)
#endif

#define ZR_(first, last) do {\
  ::memset(&first, 0,\
           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)

  ZR_(latitude_, longitude_);

#undef ZR_HELPER_
#undef ZR_

}

bool Point::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:routeguide.Point)
  for (;;) {
    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // optional int32 latitude = 1;
      case 1: {
        if (tag == 8) {
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                 input, &latitude_)));

        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(16)) goto parse_longitude;
        break;
      }

      // optional int32 longitude = 2;
      case 2: {
        if (tag == 16) {
         parse_longitude:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                 input, &longitude_)));

        } else {
          goto handle_unusual;
        }
        if (input->ExpectAtEnd()) goto success;
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0 ||
            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:routeguide.Point)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:routeguide.Point)
  return false;
#undef DO_
}

void Point::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:routeguide.Point)
  // optional int32 latitude = 1;
  if (this->latitude() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->latitude(), output);
  }

  // optional int32 longitude = 2;
  if (this->longitude() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->longitude(), output);
  }

  // @@protoc_insertion_point(serialize_end:routeguide.Point)
}

::google::protobuf::uint8* Point::InternalSerializeWithCachedSizesToArray(
    bool deterministic, ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:routeguide.Point)
  // optional int32 latitude = 1;
  if (this->latitude() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->latitude(), target);
  }

  // optional int32 longitude = 2;
  if (this->longitude() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->longitude(), target);
  }

  // @@protoc_insertion_point(serialize_to_array_end:routeguide.Point)
  return target;
}

int Point::ByteSize() const {
// @@protoc_insertion_point(message_byte_size_start:routeguide.Point)
  int total_size = 0;

  // optional int32 latitude = 1;
  if (this->latitude() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::Int32Size(
        this->latitude());
  }

  // optional int32 longitude = 2;
  if (this->longitude() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::Int32Size(
        this->longitude());
  }

  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = total_size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
  return total_size;
}

void Point::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:routeguide.Point)
  if (GOOGLE_PREDICT_FALSE(&from == this)) {
    ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
  }
  const Point* source = 
      ::google::protobuf::internal::DynamicCastToGenerated<const Point>(
          &from);
  if (source == NULL) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:routeguide.Point)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:routeguide.Point)
    MergeFrom(*source);
  }
}

void Point::MergeFrom(const Point& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:routeguide.Point)
  if (GOOGLE_PREDICT_FALSE(&from == this)) {
    ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
  }
  if (from.latitude() != 0) {
    set_latitude(from.latitude());
  }
  if (from.longitude() != 0) {
    set_longitude(from.longitude());
  }
}

void Point::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:routeguide.Point)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void Point::CopyFrom(const Point& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:routeguide.Point)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool Point::IsInitialized() const {

  return true;
}

void Point::Swap(Point* other) {
  if (other == this) return;
  InternalSwap(other);
}
void Point::InternalSwap(Point* other) {
  std::swap(latitude_, other->latitude_);
  std::swap(longitude_, other->longitude_);
  _internal_metadata_.Swap(&other->_internal_metadata_);
  std::swap(_cached_size_, other->_cached_size_);
}

::google::protobuf::Metadata Point::GetMetadata() const {
  protobuf_AssignDescriptorsOnce();
  ::google::protobuf::Metadata metadata;
  metadata.descriptor = Point_descriptor_;
  metadata.reflection = Point_reflection_;
  return metadata;
}

#if PROTOBUF_INLINE_NOT_IN_HEADERS
// Point

// optional int32 latitude = 1;
void Point::clear_latitude() {
  latitude_ = 0;
}
 ::google::protobuf::int32 Point::latitude() const {
  // @@protoc_insertion_point(field_get:routeguide.Point.latitude)
  return latitude_;
}
 void Point::set_latitude(::google::protobuf::int32 value) {
  
  latitude_ = value;
  // @@protoc_insertion_point(field_set:routeguide.Point.latitude)
}

// optional int32 longitude = 2;
void Point::clear_longitude() {
  longitude_ = 0;
}
 ::google::protobuf::int32 Point::longitude() const {
  // @@protoc_insertion_point(field_get:routeguide.Point.longitude)
  return longitude_;
}
 void Point::set_longitude(::google::protobuf::int32 value) {
  
  longitude_ = value;
  // @@protoc_insertion_point(field_set:routeguide.Point.longitude)
}

#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS

// ===================================================================

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int Rectangle::kLoFieldNumber;
const int Rectangle::kHiFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

Rectangle::Rectangle()
  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:routeguide.Rectangle)
}

void Rectangle::InitAsDefaultInstance() {
  _is_default_instance_ = true;
  lo_ = const_cast< ::routeguide::Point*>(&::routeguide::Point::default_instance());
  hi_ = const_cast< ::routeguide::Point*>(&::routeguide::Point::default_instance());
}

Rectangle::Rectangle(const Rectangle& from)
  : ::google::protobuf::Message(),
    _internal_metadata_(NULL) {
  SharedCtor();
  MergeFrom(from);
  // @@protoc_insertion_point(copy_constructor:routeguide.Rectangle)
}

void Rectangle::SharedCtor() {
    _is_default_instance_ = false;
  _cached_size_ = 0;
  lo_ = NULL;
  hi_ = NULL;
}

Rectangle::~Rectangle() {
  // @@protoc_insertion_point(destructor:routeguide.Rectangle)
  SharedDtor();
}

void Rectangle::SharedDtor() {
  if (this != default_instance_) {
    delete lo_;
    delete hi_;
  }
}

void Rectangle::SetCachedSize(int size) const {
  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* Rectangle::descriptor() {
  protobuf_AssignDescriptorsOnce();
  return Rectangle_descriptor_;
}

const Rectangle& Rectangle::default_instance() {
  if (default_instance_ == NULL) protobuf_AddDesc_route_5fguide_2eproto();
  return *default_instance_;
}

Rectangle* Rectangle::default_instance_ = NULL;

Rectangle* Rectangle::New(::google::protobuf::Arena* arena) const {
  Rectangle* n = new Rectangle;
  if (arena != NULL) {
    arena->Own(n);
  }
  return n;
}

void Rectangle::Clear() {
// @@protoc_insertion_point(message_clear_start:routeguide.Rectangle)
  if (GetArenaNoVirtual() == NULL && lo_ != NULL) delete lo_;
  lo_ = NULL;
  if (GetArenaNoVirtual() == NULL && hi_ != NULL) delete hi_;
  hi_ = NULL;
}

bool Rectangle::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:routeguide.Rectangle)
  for (;;) {
    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // optional .routeguide.Point lo = 1;
      case 1: {
        if (tag == 10) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
               input, mutable_lo()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(18)) goto parse_hi;
        break;
      }

      // optional .routeguide.Point hi = 2;
      case 2: {
        if (tag == 18) {
         parse_hi:
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
               input, mutable_hi()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectAtEnd()) goto success;
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0 ||
            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:routeguide.Rectangle)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:routeguide.Rectangle)
  return false;
#undef DO_
}

void Rectangle::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:routeguide.Rectangle)
  // optional .routeguide.Point lo = 1;
  if (this->has_lo()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      1, *this->lo_, output);
  }

  // optional .routeguide.Point hi = 2;
  if (this->has_hi()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      2, *this->hi_, output);
  }

  // @@protoc_insertion_point(serialize_end:routeguide.Rectangle)
}

::google::protobuf::uint8* Rectangle::InternalSerializeWithCachedSizesToArray(
    bool deterministic, ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:routeguide.Rectangle)
  // optional .routeguide.Point lo = 1;
  if (this->has_lo()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageNoVirtualToArray(
        1, *this->lo_, false, target);
  }

  // optional .routeguide.Point hi = 2;
  if (this->has_hi()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageNoVirtualToArray(
        2, *this->hi_, false, target);
  }

  // @@protoc_insertion_point(serialize_to_array_end:routeguide.Rectangle)
  return target;
}

int Rectangle::ByteSize() const {
// @@protoc_insertion_point(message_byte_size_start:routeguide.Rectangle)
  int total_size = 0;

  // optional .routeguide.Point lo = 1;
  if (this->has_lo()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
        *this->lo_);
  }

  // optional .routeguide.Point hi = 2;
  if (this->has_hi()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
        *this->hi_);
  }

  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = total_size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
  return total_size;
}

void Rectangle::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:routeguide.Rectangle)
  if (GOOGLE_PREDICT_FALSE(&from == this)) {
    ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
  }
  const Rectangle* source = 
      ::google::protobuf::internal::DynamicCastToGenerated<const Rectangle>(
          &from);
  if (source == NULL) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:routeguide.Rectangle)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:routeguide.Rectangle)
    MergeFrom(*source);
  }
}

void Rectangle::MergeFrom(const Rectangle& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:routeguide.Rectangle)
  if (GOOGLE_PREDICT_FALSE(&from == this)) {
    ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
  }
  if (from.has_lo()) {
    mutable_lo()->::routeguide::Point::MergeFrom(from.lo());
  }
  if (from.has_hi()) {
    mutable_hi()->::routeguide::Point::MergeFrom(from.hi());
  }
}

void Rectangle::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:routeguide.Rectangle)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void Rectangle::CopyFrom(const Rectangle& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:routeguide.Rectangle)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool Rectangle::IsInitialized() const {

  return true;
}

void Rectangle::Swap(Rectangle* other) {
  if (other == this) return;
  InternalSwap(other);
}
void Rectangle::InternalSwap(Rectangle* other) {
  std::swap(lo_, other->lo_);
  std::swap(hi_, other->hi_);
  _internal_metadata_.Swap(&other->_internal_metadata_);
  std::swap(_cached_size_, other->_cached_size_);
}

::google::protobuf::Metadata Rectangle::GetMetadata() const {
  protobuf_AssignDescriptorsOnce();
  ::google::protobuf::Metadata metadata;
  metadata.descriptor = Rectangle_descriptor_;
  metadata.reflection = Rectangle_reflection_;
  return metadata;
}

#if PROTOBUF_INLINE_NOT_IN_HEADERS
// Rectangle

// optional .routeguide.Point lo = 1;
bool Rectangle::has_lo() const {
  return !_is_default_instance_ && lo_ != NULL;
}
void Rectangle::clear_lo() {
  if (GetArenaNoVirtual() == NULL && lo_ != NULL) delete lo_;
  lo_ = NULL;
}
const ::routeguide::Point& Rectangle::lo() const {
  // @@protoc_insertion_point(field_get:routeguide.Rectangle.lo)
  return lo_ != NULL ? *lo_ : *default_instance_->lo_;
}
::routeguide::Point* Rectangle::mutable_lo() {
  
  if (lo_ == NULL) {
    lo_ = new ::routeguide::Point;
  }
  // @@protoc_insertion_point(field_mutable:routeguide.Rectangle.lo)
  return lo_;
}
::routeguide::Point* Rectangle::release_lo() {
  // @@protoc_insertion_point(field_release:routeguide.Rectangle.lo)
  
  ::routeguide::Point* temp = lo_;
  lo_ = NULL;
  return temp;
}
void Rectangle::set_allocated_lo(::routeguide::Point* lo) {
  delete lo_;
  lo_ = lo;
  if (lo) {
    
  } else {
    
  }
  // @@protoc_insertion_point(field_set_allocated:routeguide.Rectangle.lo)
}

// optional .routeguide.Point hi = 2;
bool Rectangle::has_hi() const {
  return !_is_default_instance_ && hi_ != NULL;
}
void Rectangle::clear_hi() {
  if (GetArenaNoVirtual() == NULL && hi_ != NULL) delete hi_;
  hi_ = NULL;
}
const ::routeguide::Point& Rectangle::hi() const {
  // @@protoc_insertion_point(field_get:routeguide.Rectangle.hi)
  return hi_ != NULL ? *hi_ : *default_instance_->hi_;
}
::routeguide::Point* Rectangle::mutable_hi() {
  
  if (hi_ == NULL) {
    hi_ = new ::routeguide::Point;
  }
  // @@protoc_insertion_point(field_mutable:routeguide.Rectangle.hi)
  return hi_;
}
::routeguide::Point* Rectangle::release_hi() {
  // @@protoc_insertion_point(field_release:routeguide.Rectangle.hi)
  
  ::routeguide::Point* temp = hi_;
  hi_ = NULL;
  return temp;
}
void Rectangle::set_allocated_hi(::routeguide::Point* hi) {
  delete hi_;
  hi_ = hi;
  if (hi) {
    
  } else {
    
  }
  // @@protoc_insertion_point(field_set_allocated:routeguide.Rectangle.hi)
}

#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS

// ===================================================================

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int Feature::kNameFieldNumber;
const int Feature::kLocationFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

Feature::Feature()
  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:routeguide.Feature)
}

void Feature::InitAsDefaultInstance() {
  _is_default_instance_ = true;
  location_ = const_cast< ::routeguide::Point*>(&::routeguide::Point::default_instance());
}

Feature::Feature(const Feature& from)
  : ::google::protobuf::Message(),
    _internal_metadata_(NULL) {
  SharedCtor();
  MergeFrom(from);
  // @@protoc_insertion_point(copy_constructor:routeguide.Feature)
}

void Feature::SharedCtor() {
    _is_default_instance_ = false;
  ::google::protobuf::internal::GetEmptyString();
  _cached_size_ = 0;
  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  location_ = NULL;
}

Feature::~Feature() {
  // @@protoc_insertion_point(destructor:routeguide.Feature)
  SharedDtor();
}

void Feature::SharedDtor() {
  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (this != default_instance_) {
    delete location_;
  }
}

void Feature::SetCachedSize(int size) const {
  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* Feature::descriptor() {
  protobuf_AssignDescriptorsOnce();
  return Feature_descriptor_;
}

const Feature& Feature::default_instance() {
  if (default_instance_ == NULL) protobuf_AddDesc_route_5fguide_2eproto();
  return *default_instance_;
}

Feature* Feature::default_instance_ = NULL;

Feature* Feature::New(::google::protobuf::Arena* arena) const {
  Feature* n = new Feature;
  if (arena != NULL) {
    arena->Own(n);
  }
  return n;
}

void Feature::Clear() {
// @@protoc_insertion_point(message_clear_start:routeguide.Feature)
  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (GetArenaNoVirtual() == NULL && location_ != NULL) delete location_;
  location_ = NULL;
}

bool Feature::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:routeguide.Feature)
  for (;;) {
    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // optional string name = 1;
      case 1: {
        if (tag == 10) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_name()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->name().data(), this->name().length(),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "routeguide.Feature.name"));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(18)) goto parse_location;
        break;
      }

      // optional .routeguide.Point location = 2;
      case 2: {
        if (tag == 18) {
         parse_location:
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
               input, mutable_location()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectAtEnd()) goto success;
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0 ||
            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:routeguide.Feature)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:routeguide.Feature)
  return false;
#undef DO_
}

void Feature::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:routeguide.Feature)
  // optional string name = 1;
  if (this->name().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->name().data(), this->name().length(),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "routeguide.Feature.name");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      1, this->name(), output);
  }

  // optional .routeguide.Point location = 2;
  if (this->has_location()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      2, *this->location_, output);
  }

  // @@protoc_insertion_point(serialize_end:routeguide.Feature)
}

::google::protobuf::uint8* Feature::InternalSerializeWithCachedSizesToArray(
    bool deterministic, ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:routeguide.Feature)
  // optional string name = 1;
  if (this->name().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->name().data(), this->name().length(),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "routeguide.Feature.name");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        1, this->name(), target);
  }

  // optional .routeguide.Point location = 2;
  if (this->has_location()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageNoVirtualToArray(
        2, *this->location_, false, target);
  }

  // @@protoc_insertion_point(serialize_to_array_end:routeguide.Feature)
  return target;
}

int Feature::ByteSize() const {
// @@protoc_insertion_point(message_byte_size_start:routeguide.Feature)
  int total_size = 0;

  // optional string name = 1;
  if (this->name().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->name());
  }

  // optional .routeguide.Point location = 2;
  if (this->has_location()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
        *this->location_);
  }

  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = total_size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
  return total_size;
}

void Feature::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:routeguide.Feature)
  if (GOOGLE_PREDICT_FALSE(&from == this)) {
    ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
  }
  const Feature* source = 
      ::google::protobuf::internal::DynamicCastToGenerated<const Feature>(
          &from);
  if (source == NULL) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:routeguide.Feature)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:routeguide.Feature)
    MergeFrom(*source);
  }
}

void Feature::MergeFrom(const Feature& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:routeguide.Feature)
  if (GOOGLE_PREDICT_FALSE(&from == this)) {
    ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
  }
  if (from.name().size() > 0) {

    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
  }
  if (from.has_location()) {
    mutable_location()->::routeguide::Point::MergeFrom(from.location());
  }
}

void Feature::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:routeguide.Feature)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void Feature::CopyFrom(const Feature& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:routeguide.Feature)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool Feature::IsInitialized() const {

  return true;
}

void Feature::Swap(Feature* other) {
  if (other == this) return;
  InternalSwap(other);
}
void Feature::InternalSwap(Feature* other) {
  name_.Swap(&other->name_);
  std::swap(location_, other->location_);
  _internal_metadata_.Swap(&other->_internal_metadata_);
  std::swap(_cached_size_, other->_cached_size_);
}

::google::protobuf::Metadata Feature::GetMetadata() const {
  protobuf_AssignDescriptorsOnce();
  ::google::protobuf::Metadata metadata;
  metadata.descriptor = Feature_descriptor_;
  metadata.reflection = Feature_reflection_;
  return metadata;
}

#if PROTOBUF_INLINE_NOT_IN_HEADERS
// Feature

// optional string name = 1;
void Feature::clear_name() {
  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 const ::std::string& Feature::name() const {
  // @@protoc_insertion_point(field_get:routeguide.Feature.name)
  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Feature::set_name(const ::std::string& value) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:routeguide.Feature.name)
}
 void Feature::set_name(const char* value) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:routeguide.Feature.name)
}
 void Feature::set_name(const char* value, size_t size) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:routeguide.Feature.name)
}
 ::std::string* Feature::mutable_name() {
  
  // @@protoc_insertion_point(field_mutable:routeguide.Feature.name)
  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 ::std::string* Feature::release_name() {
  // @@protoc_insertion_point(field_release:routeguide.Feature.name)
  
  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Feature::set_allocated_name(::std::string* name) {
  if (name != NULL) {
    
  } else {
    
  }
  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
  // @@protoc_insertion_point(field_set_allocated:routeguide.Feature.name)
}

// optional .routeguide.Point location = 2;
bool Feature::has_location() const {
  return !_is_default_instance_ && location_ != NULL;
}
void Feature::clear_location() {
  if (GetArenaNoVirtual() == NULL && location_ != NULL) delete location_;
  location_ = NULL;
}
const ::routeguide::Point& Feature::location() const {
  // @@protoc_insertion_point(field_get:routeguide.Feature.location)
  return location_ != NULL ? *location_ : *default_instance_->location_;
}
::routeguide::Point* Feature::mutable_location() {
  
  if (location_ == NULL) {
    location_ = new ::routeguide::Point;
  }
  // @@protoc_insertion_point(field_mutable:routeguide.Feature.location)
  return location_;
}
::routeguide::Point* Feature::release_location() {
  // @@protoc_insertion_point(field_release:routeguide.Feature.location)
  
  ::routeguide::Point* temp = location_;
  location_ = NULL;
  return temp;
}
void Feature::set_allocated_location(::routeguide::Point* location) {
  delete location_;
  location_ = location;
  if (location) {
    
  } else {
    
  }
  // @@protoc_insertion_point(field_set_allocated:routeguide.Feature.location)
}

#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS

// ===================================================================

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int RouteNote::kLocationFieldNumber;
const int RouteNote::kMessageFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

RouteNote::RouteNote()
  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:routeguide.RouteNote)
}

void RouteNote::InitAsDefaultInstance() {
  _is_default_instance_ = true;
  location_ = const_cast< ::routeguide::Point*>(&::routeguide::Point::default_instance());
}

RouteNote::RouteNote(const RouteNote& from)
  : ::google::protobuf::Message(),
    _internal_metadata_(NULL) {
  SharedCtor();
  MergeFrom(from);
  // @@protoc_insertion_point(copy_constructor:routeguide.RouteNote)
}

void RouteNote::SharedCtor() {
    _is_default_instance_ = false;
  ::google::protobuf::internal::GetEmptyString();
  _cached_size_ = 0;
  location_ = NULL;
  message_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}

RouteNote::~RouteNote() {
  // @@protoc_insertion_point(destructor:routeguide.RouteNote)
  SharedDtor();
}

void RouteNote::SharedDtor() {
  message_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (this != default_instance_) {
    delete location_;
  }
}

void RouteNote::SetCachedSize(int size) const {
  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* RouteNote::descriptor() {
  protobuf_AssignDescriptorsOnce();
  return RouteNote_descriptor_;
}

const RouteNote& RouteNote::default_instance() {
  if (default_instance_ == NULL) protobuf_AddDesc_route_5fguide_2eproto();
  return *default_instance_;
}

RouteNote* RouteNote::default_instance_ = NULL;

RouteNote* RouteNote::New(::google::protobuf::Arena* arena) const {
  RouteNote* n = new RouteNote;
  if (arena != NULL) {
    arena->Own(n);
  }
  return n;
}

void RouteNote::Clear() {
// @@protoc_insertion_point(message_clear_start:routeguide.RouteNote)
  if (GetArenaNoVirtual() == NULL && location_ != NULL) delete location_;
  location_ = NULL;
  message_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}

bool RouteNote::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:routeguide.RouteNote)
  for (;;) {
    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // optional .routeguide.Point location = 1;
      case 1: {
        if (tag == 10) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
               input, mutable_location()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(18)) goto parse_message;
        break;
      }

      // optional string message = 2;
      case 2: {
        if (tag == 18) {
         parse_message:
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_message()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->message().data(), this->message().length(),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "routeguide.RouteNote.message"));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectAtEnd()) goto success;
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0 ||
            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:routeguide.RouteNote)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:routeguide.RouteNote)
  return false;
#undef DO_
}

void RouteNote::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:routeguide.RouteNote)
  // optional .routeguide.Point location = 1;
  if (this->has_location()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      1, *this->location_, output);
  }

  // optional string message = 2;
  if (this->message().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->message().data(), this->message().length(),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "routeguide.RouteNote.message");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      2, this->message(), output);
  }

  // @@protoc_insertion_point(serialize_end:routeguide.RouteNote)
}

::google::protobuf::uint8* RouteNote::InternalSerializeWithCachedSizesToArray(
    bool deterministic, ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:routeguide.RouteNote)
  // optional .routeguide.Point location = 1;
  if (this->has_location()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageNoVirtualToArray(
        1, *this->location_, false, target);
  }

  // optional string message = 2;
  if (this->message().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->message().data(), this->message().length(),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "routeguide.RouteNote.message");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        2, this->message(), target);
  }

  // @@protoc_insertion_point(serialize_to_array_end:routeguide.RouteNote)
  return target;
}

int RouteNote::ByteSize() const {
// @@protoc_insertion_point(message_byte_size_start:routeguide.RouteNote)
  int total_size = 0;

  // optional .routeguide.Point location = 1;
  if (this->has_location()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
        *this->location_);
  }

  // optional string message = 2;
  if (this->message().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->message());
  }

  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = total_size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
  return total_size;
}

void RouteNote::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:routeguide.RouteNote)
  if (GOOGLE_PREDICT_FALSE(&from == this)) {
    ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
  }
  const RouteNote* source = 
      ::google::protobuf::internal::DynamicCastToGenerated<const RouteNote>(
          &from);
  if (source == NULL) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:routeguide.RouteNote)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:routeguide.RouteNote)
    MergeFrom(*source);
  }
}

void RouteNote::MergeFrom(const RouteNote& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:routeguide.RouteNote)
  if (GOOGLE_PREDICT_FALSE(&from == this)) {
    ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
  }
  if (from.has_location()) {
    mutable_location()->::routeguide::Point::MergeFrom(from.location());
  }
  if (from.message().size() > 0) {

    message_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.message_);
  }
}

void RouteNote::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:routeguide.RouteNote)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void RouteNote::CopyFrom(const RouteNote& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:routeguide.RouteNote)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool RouteNote::IsInitialized() const {

  return true;
}

void RouteNote::Swap(RouteNote* other) {
  if (other == this) return;
  InternalSwap(other);
}
void RouteNote::InternalSwap(RouteNote* other) {
  std::swap(location_, other->location_);
  message_.Swap(&other->message_);
  _internal_metadata_.Swap(&other->_internal_metadata_);
  std::swap(_cached_size_, other->_cached_size_);
}

::google::protobuf::Metadata RouteNote::GetMetadata() const {
  protobuf_AssignDescriptorsOnce();
  ::google::protobuf::Metadata metadata;
  metadata.descriptor = RouteNote_descriptor_;
  metadata.reflection = RouteNote_reflection_;
  return metadata;
}

#if PROTOBUF_INLINE_NOT_IN_HEADERS
// RouteNote

// optional .routeguide.Point location = 1;
bool RouteNote::has_location() const {
  return !_is_default_instance_ && location_ != NULL;
}
void RouteNote::clear_location() {
  if (GetArenaNoVirtual() == NULL && location_ != NULL) delete location_;
  location_ = NULL;
}
const ::routeguide::Point& RouteNote::location() const {
  // @@protoc_insertion_point(field_get:routeguide.RouteNote.location)
  return location_ != NULL ? *location_ : *default_instance_->location_;
}
::routeguide::Point* RouteNote::mutable_location() {
  
  if (location_ == NULL) {
    location_ = new ::routeguide::Point;
  }
  // @@protoc_insertion_point(field_mutable:routeguide.RouteNote.location)
  return location_;
}
::routeguide::Point* RouteNote::release_location() {
  // @@protoc_insertion_point(field_release:routeguide.RouteNote.location)
  
  ::routeguide::Point* temp = location_;
  location_ = NULL;
  return temp;
}
void RouteNote::set_allocated_location(::routeguide::Point* location) {
  delete location_;
  location_ = location;
  if (location) {
    
  } else {
    
  }
  // @@protoc_insertion_point(field_set_allocated:routeguide.RouteNote.location)
}

// optional string message = 2;
void RouteNote::clear_message() {
  message_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 const ::std::string& RouteNote::message() const {
  // @@protoc_insertion_point(field_get:routeguide.RouteNote.message)
  return message_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void RouteNote::set_message(const ::std::string& value) {
  
  message_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:routeguide.RouteNote.message)
}
 void RouteNote::set_message(const char* value) {
  
  message_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:routeguide.RouteNote.message)
}
 void RouteNote::set_message(const char* value, size_t size) {
  
  message_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:routeguide.RouteNote.message)
}
 ::std::string* RouteNote::mutable_message() {
  
  // @@protoc_insertion_point(field_mutable:routeguide.RouteNote.message)
  return message_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 ::std::string* RouteNote::release_message() {
  // @@protoc_insertion_point(field_release:routeguide.RouteNote.message)
  
  return message_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void RouteNote::set_allocated_message(::std::string* message) {
  if (message != NULL) {
    
  } else {
    
  }
  message_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), message);
  // @@protoc_insertion_point(field_set_allocated:routeguide.RouteNote.message)
}

#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS

// ===================================================================

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int RouteSummary::kPointCountFieldNumber;
const int RouteSummary::kFeatureCountFieldNumber;
const int RouteSummary::kDistanceFieldNumber;
const int RouteSummary::kElapsedTimeFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

RouteSummary::RouteSummary()
  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:routeguide.RouteSummary)
}

void RouteSummary::InitAsDefaultInstance() {
  _is_default_instance_ = true;
}

RouteSummary::RouteSummary(const RouteSummary& from)
  : ::google::protobuf::Message(),
    _internal_metadata_(NULL) {
  SharedCtor();
  MergeFrom(from);
  // @@protoc_insertion_point(copy_constructor:routeguide.RouteSummary)
}

void RouteSummary::SharedCtor() {
    _is_default_instance_ = false;
  _cached_size_ = 0;
  point_count_ = 0;
  feature_count_ = 0;
  distance_ = 0;
  elapsed_time_ = 0;
}

RouteSummary::~RouteSummary() {
  // @@protoc_insertion_point(destructor:routeguide.RouteSummary)
  SharedDtor();
}

void RouteSummary::SharedDtor() {
  if (this != default_instance_) {
  }
}

void RouteSummary::SetCachedSize(int size) const {
  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* RouteSummary::descriptor() {
  protobuf_AssignDescriptorsOnce();
  return RouteSummary_descriptor_;
}

const RouteSummary& RouteSummary::default_instance() {
  if (default_instance_ == NULL) protobuf_AddDesc_route_5fguide_2eproto();
  return *default_instance_;
}

RouteSummary* RouteSummary::default_instance_ = NULL;

RouteSummary* RouteSummary::New(::google::protobuf::Arena* arena) const {
  RouteSummary* n = new RouteSummary;
  if (arena != NULL) {
    arena->Own(n);
  }
  return n;
}

void RouteSummary::Clear() {
// @@protoc_insertion_point(message_clear_start:routeguide.RouteSummary)
#if defined(__clang__)
#define ZR_HELPER_(f) \
  _Pragma("clang diagnostic push") \
  _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
  __builtin_offsetof(RouteSummary, f) \
  _Pragma("clang diagnostic pop")
#else
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
  &reinterpret_cast<RouteSummary*>(16)->f)
#endif

#define ZR_(first, last) do {\
  ::memset(&first, 0,\
           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)

  ZR_(point_count_, elapsed_time_);

#undef ZR_HELPER_
#undef ZR_

}

bool RouteSummary::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:routeguide.RouteSummary)
  for (;;) {
    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // optional int32 point_count = 1;
      case 1: {
        if (tag == 8) {
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                 input, &point_count_)));

        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(16)) goto parse_feature_count;
        break;
      }

      // optional int32 feature_count = 2;
      case 2: {
        if (tag == 16) {
         parse_feature_count:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                 input, &feature_count_)));

        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(24)) goto parse_distance;
        break;
      }

      // optional int32 distance = 3;
      case 3: {
        if (tag == 24) {
         parse_distance:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                 input, &distance_)));

        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(32)) goto parse_elapsed_time;
        break;
      }

      // optional int32 elapsed_time = 4;
      case 4: {
        if (tag == 32) {
         parse_elapsed_time:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                 input, &elapsed_time_)));

        } else {
          goto handle_unusual;
        }
        if (input->ExpectAtEnd()) goto success;
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0 ||
            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:routeguide.RouteSummary)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:routeguide.RouteSummary)
  return false;
#undef DO_
}

void RouteSummary::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:routeguide.RouteSummary)
  // optional int32 point_count = 1;
  if (this->point_count() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->point_count(), output);
  }

  // optional int32 feature_count = 2;
  if (this->feature_count() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->feature_count(), output);
  }

  // optional int32 distance = 3;
  if (this->distance() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->distance(), output);
  }

  // optional int32 elapsed_time = 4;
  if (this->elapsed_time() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteInt32(4, this->elapsed_time(), output);
  }

  // @@protoc_insertion_point(serialize_end:routeguide.RouteSummary)
}

::google::protobuf::uint8* RouteSummary::InternalSerializeWithCachedSizesToArray(
    bool deterministic, ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:routeguide.RouteSummary)
  // optional int32 point_count = 1;
  if (this->point_count() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->point_count(), target);
  }

  // optional int32 feature_count = 2;
  if (this->feature_count() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->feature_count(), target);
  }

  // optional int32 distance = 3;
  if (this->distance() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->distance(), target);
  }

  // optional int32 elapsed_time = 4;
  if (this->elapsed_time() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(4, this->elapsed_time(), target);
  }

  // @@protoc_insertion_point(serialize_to_array_end:routeguide.RouteSummary)
  return target;
}

int RouteSummary::ByteSize() const {
// @@protoc_insertion_point(message_byte_size_start:routeguide.RouteSummary)
  int total_size = 0;

  // optional int32 point_count = 1;
  if (this->point_count() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::Int32Size(
        this->point_count());
  }

  // optional int32 feature_count = 2;
  if (this->feature_count() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::Int32Size(
        this->feature_count());
  }

  // optional int32 distance = 3;
  if (this->distance() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::Int32Size(
        this->distance());
  }

  // optional int32 elapsed_time = 4;
  if (this->elapsed_time() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::Int32Size(
        this->elapsed_time());
  }

  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = total_size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
  return total_size;
}

void RouteSummary::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:routeguide.RouteSummary)
  if (GOOGLE_PREDICT_FALSE(&from == this)) {
    ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
  }
  const RouteSummary* source = 
      ::google::protobuf::internal::DynamicCastToGenerated<const RouteSummary>(
          &from);
  if (source == NULL) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:routeguide.RouteSummary)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:routeguide.RouteSummary)
    MergeFrom(*source);
  }
}

void RouteSummary::MergeFrom(const RouteSummary& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:routeguide.RouteSummary)
  if (GOOGLE_PREDICT_FALSE(&from == this)) {
    ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
  }
  if (from.point_count() != 0) {
    set_point_count(from.point_count());
  }
  if (from.feature_count() != 0) {
    set_feature_count(from.feature_count());
  }
  if (from.distance() != 0) {
    set_distance(from.distance());
  }
  if (from.elapsed_time() != 0) {
    set_elapsed_time(from.elapsed_time());
  }
}

void RouteSummary::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:routeguide.RouteSummary)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void RouteSummary::CopyFrom(const RouteSummary& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:routeguide.RouteSummary)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool RouteSummary::IsInitialized() const {

  return true;
}

void RouteSummary::Swap(RouteSummary* other) {
  if (other == this) return;
  InternalSwap(other);
}
void RouteSummary::InternalSwap(RouteSummary* other) {
  std::swap(point_count_, other->point_count_);
  std::swap(feature_count_, other->feature_count_);
  std::swap(distance_, other->distance_);
  std::swap(elapsed_time_, other->elapsed_time_);
  _internal_metadata_.Swap(&other->_internal_metadata_);
  std::swap(_cached_size_, other->_cached_size_);
}

::google::protobuf::Metadata RouteSummary::GetMetadata() const {
  protobuf_AssignDescriptorsOnce();
  ::google::protobuf::Metadata metadata;
  metadata.descriptor = RouteSummary_descriptor_;
  metadata.reflection = RouteSummary_reflection_;
  return metadata;
}

#if PROTOBUF_INLINE_NOT_IN_HEADERS
// RouteSummary

// optional int32 point_count = 1;
void RouteSummary::clear_point_count() {
  point_count_ = 0;
}
 ::google::protobuf::int32 RouteSummary::point_count() const {
  // @@protoc_insertion_point(field_get:routeguide.RouteSummary.point_count)
  return point_count_;
}
 void RouteSummary::set_point_count(::google::protobuf::int32 value) {
  
  point_count_ = value;
  // @@protoc_insertion_point(field_set:routeguide.RouteSummary.point_count)
}

// optional int32 feature_count = 2;
void RouteSummary::clear_feature_count() {
  feature_count_ = 0;
}
 ::google::protobuf::int32 RouteSummary::feature_count() const {
  // @@protoc_insertion_point(field_get:routeguide.RouteSummary.feature_count)
  return feature_count_;
}
 void RouteSummary::set_feature_count(::google::protobuf::int32 value) {
  
  feature_count_ = value;
  // @@protoc_insertion_point(field_set:routeguide.RouteSummary.feature_count)
}

// optional int32 distance = 3;
void RouteSummary::clear_distance() {
  distance_ = 0;
}
 ::google::protobuf::int32 RouteSummary::distance() const {
  // @@protoc_insertion_point(field_get:routeguide.RouteSummary.distance)
  return distance_;
}
 void RouteSummary::set_distance(::google::protobuf::int32 value) {
  
  distance_ = value;
  // @@protoc_insertion_point(field_set:routeguide.RouteSummary.distance)
}

// optional int32 elapsed_time = 4;
void RouteSummary::clear_elapsed_time() {
  elapsed_time_ = 0;
}
 ::google::protobuf::int32 RouteSummary::elapsed_time() const {
  // @@protoc_insertion_point(field_get:routeguide.RouteSummary.elapsed_time)
  return elapsed_time_;
}
 void RouteSummary::set_elapsed_time(::google::protobuf::int32 value) {
  
  elapsed_time_ = value;
  // @@protoc_insertion_point(field_set:routeguide.RouteSummary.elapsed_time)
}

#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS

// @@protoc_insertion_point(namespace_scope)

}  // namespace routeguide

// @@protoc_insertion_point(global_scope)

route_guide.grpc.pb.h
// Generated by the gRPC C++ plugin.
// If you make any local change, they will be lost.
// source: route_guide.proto
// 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.
//
#ifndef GRPC_route_5fguide_2eproto__INCLUDED
#define GRPC_route_5fguide_2eproto__INCLUDED

#include "route_guide.pb.h"

#include <grpc++/impl/codegen/async_stream.h>
#include <grpc++/impl/codegen/async_unary_call.h>
#include <grpc++/impl/codegen/method_handler_impl.h>
#include <grpc++/impl/codegen/proto_utils.h>
#include <grpc++/impl/codegen/rpc_method.h>
#include <grpc++/impl/codegen/service_type.h>
#include <grpc++/impl/codegen/status.h>
#include <grpc++/impl/codegen/stub_options.h>
#include <grpc++/impl/codegen/sync_stream.h>

namespace grpc {
class CompletionQueue;
class Channel;
class RpcService;
class ServerCompletionQueue;
class ServerContext;
}  // namespace grpc

namespace routeguide {

// Interface exported by the server.
class RouteGuide final {
 public:
  class StubInterface {
   public:
    virtual ~StubInterface() {}
    // 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.
    virtual ::grpc::Status GetFeature(::grpc::ClientContext* context, const ::routeguide::Point& request, ::routeguide::Feature* response) = 0;
    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::routeguide::Feature>> AsyncGetFeature(::grpc::ClientContext* context, const ::routeguide::Point& request, ::grpc::CompletionQueue* cq) {
      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::routeguide::Feature>>(AsyncGetFeatureRaw(context, request, cq));
    }
    // 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.
    std::unique_ptr< ::grpc::ClientReaderInterface< ::routeguide::Feature>> ListFeatures(::grpc::ClientContext* context, const ::routeguide::Rectangle& request) {
      return std::unique_ptr< ::grpc::ClientReaderInterface< ::routeguide::Feature>>(ListFeaturesRaw(context, request));
    }
    std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::routeguide::Feature>> AsyncListFeatures(::grpc::ClientContext* context, const ::routeguide::Rectangle& request, ::grpc::CompletionQueue* cq, void* tag) {
      return std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::routeguide::Feature>>(AsyncListFeaturesRaw(context, request, cq, tag));
    }
    // A client-to-server streaming RPC.
    //
    // Accepts a stream of Points on a route being traversed, returning a
    // RouteSummary when traversal is completed.
    std::unique_ptr< ::grpc::ClientWriterInterface< ::routeguide::Point>> RecordRoute(::grpc::ClientContext* context, ::routeguide::RouteSummary* response) {
      return std::unique_ptr< ::grpc::ClientWriterInterface< ::routeguide::Point>>(RecordRouteRaw(context, response));
    }
    std::unique_ptr< ::grpc::ClientAsyncWriterInterface< ::routeguide::Point>> AsyncRecordRoute(::grpc::ClientContext* context, ::routeguide::RouteSummary* response, ::grpc::CompletionQueue* cq, void* tag) {
      return std::unique_ptr< ::grpc::ClientAsyncWriterInterface< ::routeguide::Point>>(AsyncRecordRouteRaw(context, response, cq, tag));
    }
    // 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).
    std::unique_ptr< ::grpc::ClientReaderWriterInterface< ::routeguide::RouteNote, ::routeguide::RouteNote>> RouteChat(::grpc::ClientContext* context) {
      return std::unique_ptr< ::grpc::ClientReaderWriterInterface< ::routeguide::RouteNote, ::routeguide::RouteNote>>(RouteChatRaw(context));
    }
    std::unique_ptr< ::grpc::ClientAsyncReaderWriterInterface< ::routeguide::RouteNote, ::routeguide::RouteNote>> AsyncRouteChat(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq, void* tag) {
      return std::unique_ptr< ::grpc::ClientAsyncReaderWriterInterface< ::routeguide::RouteNote, ::routeguide::RouteNote>>(AsyncRouteChatRaw(context, cq, tag));
    }
  private:
    virtual ::grpc::ClientAsyncResponseReaderInterface< ::routeguide::Feature>* AsyncGetFeatureRaw(::grpc::ClientContext* context, const ::routeguide::Point& request, ::grpc::CompletionQueue* cq) = 0;
    virtual ::grpc::ClientReaderInterface< ::routeguide::Feature>* ListFeaturesRaw(::grpc::ClientContext* context, const ::routeguide::Rectangle& request) = 0;
    virtual ::grpc::ClientAsyncReaderInterface< ::routeguide::Feature>* AsyncListFeaturesRaw(::grpc::ClientContext* context, const ::routeguide::Rectangle& request, ::grpc::CompletionQueue* cq, void* tag) = 0;
    virtual ::grpc::ClientWriterInterface< ::routeguide::Point>* RecordRouteRaw(::grpc::ClientContext* context, ::routeguide::RouteSummary* response) = 0;
    virtual ::grpc::ClientAsyncWriterInterface< ::routeguide::Point>* AsyncRecordRouteRaw(::grpc::ClientContext* context, ::routeguide::RouteSummary* response, ::grpc::CompletionQueue* cq, void* tag) = 0;
    virtual ::grpc::ClientReaderWriterInterface< ::routeguide::RouteNote, ::routeguide::RouteNote>* RouteChatRaw(::grpc::ClientContext* context) = 0;
    virtual ::grpc::ClientAsyncReaderWriterInterface< ::routeguide::RouteNote, ::routeguide::RouteNote>* AsyncRouteChatRaw(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq, void* tag) = 0;
  };
  class Stub final : public StubInterface {
   public:
    Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel);
    ::grpc::Status GetFeature(::grpc::ClientContext* context, const ::routeguide::Point& request, ::routeguide::Feature* response) override;
    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::routeguide::Feature>> AsyncGetFeature(::grpc::ClientContext* context, const ::routeguide::Point& request, ::grpc::CompletionQueue* cq) {
      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::routeguide::Feature>>(AsyncGetFeatureRaw(context, request, cq));
    }
    std::unique_ptr< ::grpc::ClientReader< ::routeguide::Feature>> ListFeatures(::grpc::ClientContext* context, const ::routeguide::Rectangle& request) {
      return std::unique_ptr< ::grpc::ClientReader< ::routeguide::Feature>>(ListFeaturesRaw(context, request));
    }
    std::unique_ptr< ::grpc::ClientAsyncReader< ::routeguide::Feature>> AsyncListFeatures(::grpc::ClientContext* context, const ::routeguide::Rectangle& request, ::grpc::CompletionQueue* cq, void* tag) {
      return std::unique_ptr< ::grpc::ClientAsyncReader< ::routeguide::Feature>>(AsyncListFeaturesRaw(context, request, cq, tag));
    }
    std::unique_ptr< ::grpc::ClientWriter< ::routeguide::Point>> RecordRoute(::grpc::ClientContext* context, ::routeguide::RouteSummary* response) {
      return std::unique_ptr< ::grpc::ClientWriter< ::routeguide::Point>>(RecordRouteRaw(context, response));
    }
    std::unique_ptr< ::grpc::ClientAsyncWriter< ::routeguide::Point>> AsyncRecordRoute(::grpc::ClientContext* context, ::routeguide::RouteSummary* response, ::grpc::CompletionQueue* cq, void* tag) {
      return std::unique_ptr< ::grpc::ClientAsyncWriter< ::routeguide::Point>>(AsyncRecordRouteRaw(context, response, cq, tag));
    }
    std::unique_ptr< ::grpc::ClientReaderWriter< ::routeguide::RouteNote, ::routeguide::RouteNote>> RouteChat(::grpc::ClientContext* context) {
      return std::unique_ptr< ::grpc::ClientReaderWriter< ::routeguide::RouteNote, ::routeguide::RouteNote>>(RouteChatRaw(context));
    }
    std::unique_ptr<  ::grpc::ClientAsyncReaderWriter< ::routeguide::RouteNote, ::routeguide::RouteNote>> AsyncRouteChat(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq, void* tag) {
      return std::unique_ptr< ::grpc::ClientAsyncReaderWriter< ::routeguide::RouteNote, ::routeguide::RouteNote>>(AsyncRouteChatRaw(context, cq, tag));
    }

   private:
    std::shared_ptr< ::grpc::ChannelInterface> channel_;
    ::grpc::ClientAsyncResponseReader< ::routeguide::Feature>* AsyncGetFeatureRaw(::grpc::ClientContext* context, const ::routeguide::Point& request, ::grpc::CompletionQueue* cq) override;
    ::grpc::ClientReader< ::routeguide::Feature>* ListFeaturesRaw(::grpc::ClientContext* context, const ::routeguide::Rectangle& request) override;
    ::grpc::ClientAsyncReader< ::routeguide::Feature>* AsyncListFeaturesRaw(::grpc::ClientContext* context, const ::routeguide::Rectangle& request, ::grpc::CompletionQueue* cq, void* tag) override;
    ::grpc::ClientWriter< ::routeguide::Point>* RecordRouteRaw(::grpc::ClientContext* context, ::routeguide::RouteSummary* response) override;
    ::grpc::ClientAsyncWriter< ::routeguide::Point>* AsyncRecordRouteRaw(::grpc::ClientContext* context, ::routeguide::RouteSummary* response, ::grpc::CompletionQueue* cq, void* tag) override;
    ::grpc::ClientReaderWriter< ::routeguide::RouteNote, ::routeguide::RouteNote>* RouteChatRaw(::grpc::ClientContext* context) override;
    ::grpc::ClientAsyncReaderWriter< ::routeguide::RouteNote, ::routeguide::RouteNote>* AsyncRouteChatRaw(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq, void* tag) override;
    const ::grpc::RpcMethod rpcmethod_GetFeature_;
    const ::grpc::RpcMethod rpcmethod_ListFeatures_;
    const ::grpc::RpcMethod rpcmethod_RecordRoute_;
    const ::grpc::RpcMethod rpcmethod_RouteChat_;
  };
  static std::unique_ptr<Stub> NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions());

  class Service : public ::grpc::Service {
   public:
    Service();
    virtual ~Service();
    // 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.
    virtual ::grpc::Status GetFeature(::grpc::ServerContext* context, const ::routeguide::Point* request, ::routeguide::Feature* response);
    // 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.
    virtual ::grpc::Status ListFeatures(::grpc::ServerContext* context, const ::routeguide::Rectangle* request, ::grpc::ServerWriter< ::routeguide::Feature>* writer);
    // A client-to-server streaming RPC.
    //
    // Accepts a stream of Points on a route being traversed, returning a
    // RouteSummary when traversal is completed.
    virtual ::grpc::Status RecordRoute(::grpc::ServerContext* context, ::grpc::ServerReader< ::routeguide::Point>* reader, ::routeguide::RouteSummary* response);
    // 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).
    virtual ::grpc::Status RouteChat(::grpc::ServerContext* context, ::grpc::ServerReaderWriter< ::routeguide::RouteNote, ::routeguide::RouteNote>* stream);
  };
  template <class BaseClass>
  class WithAsyncMethod_GetFeature : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithAsyncMethod_GetFeature() {
      ::grpc::Service::MarkMethodAsync(0);
    }
    ~WithAsyncMethod_GetFeature() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable synchronous version of this method
    ::grpc::Status GetFeature(::grpc::ServerContext* context, const ::routeguide::Point* request, ::routeguide::Feature* response) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
    void RequestGetFeature(::grpc::ServerContext* context, ::routeguide::Point* request, ::grpc::ServerAsyncResponseWriter< ::routeguide::Feature>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
      ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag);
    }
  };
  template <class BaseClass>
  class WithAsyncMethod_ListFeatures : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithAsyncMethod_ListFeatures() {
      ::grpc::Service::MarkMethodAsync(1);
    }
    ~WithAsyncMethod_ListFeatures() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable synchronous version of this method
    ::grpc::Status ListFeatures(::grpc::ServerContext* context, const ::routeguide::Rectangle* request, ::grpc::ServerWriter< ::routeguide::Feature>* writer) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
    void RequestListFeatures(::grpc::ServerContext* context, ::routeguide::Rectangle* request, ::grpc::ServerAsyncWriter< ::routeguide::Feature>* writer, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
      ::grpc::Service::RequestAsyncServerStreaming(1, context, request, writer, new_call_cq, notification_cq, tag);
    }
  };
  template <class BaseClass>
  class WithAsyncMethod_RecordRoute : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithAsyncMethod_RecordRoute() {
      ::grpc::Service::MarkMethodAsync(2);
    }
    ~WithAsyncMethod_RecordRoute() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable synchronous version of this method
    ::grpc::Status RecordRoute(::grpc::ServerContext* context, ::grpc::ServerReader< ::routeguide::Point>* reader, ::routeguide::RouteSummary* response) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
    void RequestRecordRoute(::grpc::ServerContext* context, ::grpc::ServerAsyncReader< ::routeguide::RouteSummary, ::routeguide::Point>* reader, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
      ::grpc::Service::RequestAsyncClientStreaming(2, context, reader, new_call_cq, notification_cq, tag);
    }
  };
  template <class BaseClass>
  class WithAsyncMethod_RouteChat : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithAsyncMethod_RouteChat() {
      ::grpc::Service::MarkMethodAsync(3);
    }
    ~WithAsyncMethod_RouteChat() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable synchronous version of this method
    ::grpc::Status RouteChat(::grpc::ServerContext* context, ::grpc::ServerReaderWriter< ::routeguide::RouteNote, ::routeguide::RouteNote>* stream) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
    void RequestRouteChat(::grpc::ServerContext* context, ::grpc::ServerAsyncReaderWriter< ::routeguide::RouteNote, ::routeguide::RouteNote>* stream, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
      ::grpc::Service::RequestAsyncBidiStreaming(3, context, stream, new_call_cq, notification_cq, tag);
    }
  };
  typedef WithAsyncMethod_GetFeature<WithAsyncMethod_ListFeatures<WithAsyncMethod_RecordRoute<WithAsyncMethod_RouteChat<Service > > > > AsyncService;
  template <class BaseClass>
  class WithGenericMethod_GetFeature : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithGenericMethod_GetFeature() {
      ::grpc::Service::MarkMethodGeneric(0);
    }
    ~WithGenericMethod_GetFeature() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable synchronous version of this method
    ::grpc::Status GetFeature(::grpc::ServerContext* context, const ::routeguide::Point* request, ::routeguide::Feature* response) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
  };
  template <class BaseClass>
  class WithGenericMethod_ListFeatures : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithGenericMethod_ListFeatures() {
      ::grpc::Service::MarkMethodGeneric(1);
    }
    ~WithGenericMethod_ListFeatures() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable synchronous version of this method
    ::grpc::Status ListFeatures(::grpc::ServerContext* context, const ::routeguide::Rectangle* request, ::grpc::ServerWriter< ::routeguide::Feature>* writer) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
  };
  template <class BaseClass>
  class WithGenericMethod_RecordRoute : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithGenericMethod_RecordRoute() {
      ::grpc::Service::MarkMethodGeneric(2);
    }
    ~WithGenericMethod_RecordRoute() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable synchronous version of this method
    ::grpc::Status RecordRoute(::grpc::ServerContext* context, ::grpc::ServerReader< ::routeguide::Point>* reader, ::routeguide::RouteSummary* response) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
  };
  template <class BaseClass>
  class WithGenericMethod_RouteChat : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithGenericMethod_RouteChat() {
      ::grpc::Service::MarkMethodGeneric(3);
    }
    ~WithGenericMethod_RouteChat() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable synchronous version of this method
    ::grpc::Status RouteChat(::grpc::ServerContext* context, ::grpc::ServerReaderWriter< ::routeguide::RouteNote, ::routeguide::RouteNote>* stream) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
  };
  template <class BaseClass>
  class WithStreamedUnaryMethod_GetFeature : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithStreamedUnaryMethod_GetFeature() {
      ::grpc::Service::MarkMethodStreamed(0,
        new ::grpc::StreamedUnaryHandler< ::routeguide::Point, ::routeguide::Feature>(std::bind(&WithStreamedUnaryMethod_GetFeature<BaseClass>::StreamedGetFeature, this, std::placeholders::_1, std::placeholders::_2)));
    }
    ~WithStreamedUnaryMethod_GetFeature() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable regular version of this method
    ::grpc::Status GetFeature(::grpc::ServerContext* context, const ::routeguide::Point* request, ::routeguide::Feature* response) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
    // replace default version of method with streamed unary
    virtual ::grpc::Status StreamedGetFeature(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::routeguide::Point,::routeguide::Feature>* server_unary_streamer) = 0;
  };
  typedef WithStreamedUnaryMethod_GetFeature<Service > StreamedUnaryService;
  template <class BaseClass>
  class WithSplitStreamingMethod_ListFeatures : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithSplitStreamingMethod_ListFeatures() {
      ::grpc::Service::MarkMethodStreamed(1,
        new ::grpc::SplitServerStreamingHandler< ::routeguide::Rectangle, ::routeguide::Feature>(std::bind(&WithSplitStreamingMethod_ListFeatures<BaseClass>::StreamedListFeatures, this, std::placeholders::_1, std::placeholders::_2)));
    }
    ~WithSplitStreamingMethod_ListFeatures() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable regular version of this method
    ::grpc::Status ListFeatures(::grpc::ServerContext* context, const ::routeguide::Rectangle* request, ::grpc::ServerWriter< ::routeguide::Feature>* writer) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
    // replace default version of method with split streamed
    virtual ::grpc::Status StreamedListFeatures(::grpc::ServerContext* context, ::grpc::ServerSplitStreamer< ::routeguide::Rectangle,::routeguide::Feature>* server_split_streamer) = 0;
  };
  typedef WithSplitStreamingMethod_ListFeatures<Service > SplitStreamedService;
  typedef WithStreamedUnaryMethod_GetFeature<WithSplitStreamingMethod_ListFeatures<Service > > StreamedService;
};

}  // namespace routeguide


#endif  // GRPC_route_5fguide_2eproto__INCLUDED

route_guide.grpc.pb.cc
// Generated by the gRPC C++ plugin.
// If you make any local change, they will be lost.
// source: route_guide.proto

#include "route_guide.pb.h"
#include "route_guide.grpc.pb.h"

#include <grpc++/impl/codegen/async_stream.h>
#include <grpc++/impl/codegen/async_unary_call.h>
#include <grpc++/impl/codegen/channel_interface.h>
#include <grpc++/impl/codegen/client_unary_call.h>
#include <grpc++/impl/codegen/method_handler_impl.h>
#include <grpc++/impl/codegen/rpc_service_method.h>
#include <grpc++/impl/codegen/service_type.h>
#include <grpc++/impl/codegen/sync_stream.h>
namespace routeguide {

static const char* RouteGuide_method_names[] = {
  "/routeguide.RouteGuide/GetFeature",
  "/routeguide.RouteGuide/ListFeatures",
  "/routeguide.RouteGuide/RecordRoute",
  "/routeguide.RouteGuide/RouteChat",
};

std::unique_ptr< RouteGuide::Stub> RouteGuide::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) {
  std::unique_ptr< RouteGuide::Stub> stub(new RouteGuide::Stub(channel));
  return stub;
}

RouteGuide::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel)
  : channel_(channel), rpcmethod_GetFeature_(RouteGuide_method_names[0], ::grpc::RpcMethod::NORMAL_RPC, channel)
  , rpcmethod_ListFeatures_(RouteGuide_method_names[1], ::grpc::RpcMethod::SERVER_STREAMING, channel)
  , rpcmethod_RecordRoute_(RouteGuide_method_names[2], ::grpc::RpcMethod::CLIENT_STREAMING, channel)
  , rpcmethod_RouteChat_(RouteGuide_method_names[3], ::grpc::RpcMethod::BIDI_STREAMING, channel)
  {}

::grpc::Status RouteGuide::Stub::GetFeature(::grpc::ClientContext* context, const ::routeguide::Point& request, ::routeguide::Feature* response) {
  return ::grpc::BlockingUnaryCall(channel_.get(), rpcmethod_GetFeature_, context, request, response);
}

::grpc::ClientAsyncResponseReader< ::routeguide::Feature>* RouteGuide::Stub::AsyncGetFeatureRaw(::grpc::ClientContext* context, const ::routeguide::Point& request, ::grpc::CompletionQueue* cq) {
  return new ::grpc::ClientAsyncResponseReader< ::routeguide::Feature>(channel_.get(), cq, rpcmethod_GetFeature_, context, request);
}

::grpc::ClientReader< ::routeguide::Feature>* RouteGuide::Stub::ListFeaturesRaw(::grpc::ClientContext* context, const ::routeguide::Rectangle& request) {
  return new ::grpc::ClientReader< ::routeguide::Feature>(channel_.get(), rpcmethod_ListFeatures_, context, request);
}

::grpc::ClientAsyncReader< ::routeguide::Feature>* RouteGuide::Stub::AsyncListFeaturesRaw(::grpc::ClientContext* context, const ::routeguide::Rectangle& request, ::grpc::CompletionQueue* cq, void* tag) {
  return new ::grpc::ClientAsyncReader< ::routeguide::Feature>(channel_.get(), cq, rpcmethod_ListFeatures_, context, request, tag);
}

::grpc::ClientWriter< ::routeguide::Point>* RouteGuide::Stub::RecordRouteRaw(::grpc::ClientContext* context, ::routeguide::RouteSummary* response) {
  return new ::grpc::ClientWriter< ::routeguide::Point>(channel_.get(), rpcmethod_RecordRoute_, context, response);
}

::grpc::ClientAsyncWriter< ::routeguide::Point>* RouteGuide::Stub::AsyncRecordRouteRaw(::grpc::ClientContext* context, ::routeguide::RouteSummary* response, ::grpc::CompletionQueue* cq, void* tag) {
  return new ::grpc::ClientAsyncWriter< ::routeguide::Point>(channel_.get(), cq, rpcmethod_RecordRoute_, context, response, tag);
}

::grpc::ClientReaderWriter< ::routeguide::RouteNote, ::routeguide::RouteNote>* RouteGuide::Stub::RouteChatRaw(::grpc::ClientContext* context) {
  return new ::grpc::ClientReaderWriter< ::routeguide::RouteNote, ::routeguide::RouteNote>(channel_.get(), rpcmethod_RouteChat_, context);
}

::grpc::ClientAsyncReaderWriter< ::routeguide::RouteNote, ::routeguide::RouteNote>* RouteGuide::Stub::AsyncRouteChatRaw(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq, void* tag) {
  return new ::grpc::ClientAsyncReaderWriter< ::routeguide::RouteNote, ::routeguide::RouteNote>(channel_.get(), cq, rpcmethod_RouteChat_, context, tag);
}

RouteGuide::Service::Service() {
  AddMethod(new ::grpc::RpcServiceMethod(
      RouteGuide_method_names[0],
      ::grpc::RpcMethod::NORMAL_RPC,
      new ::grpc::RpcMethodHandler< RouteGuide::Service, ::routeguide::Point, ::routeguide::Feature>(
          std::mem_fn(&RouteGuide::Service::GetFeature), this)));
  AddMethod(new ::grpc::RpcServiceMethod(
      RouteGuide_method_names[1],
      ::grpc::RpcMethod::SERVER_STREAMING,
      new ::grpc::ServerStreamingHandler< RouteGuide::Service, ::routeguide::Rectangle, ::routeguide::Feature>(
          std::mem_fn(&RouteGuide::Service::ListFeatures), this)));
  AddMethod(new ::grpc::RpcServiceMethod(
      RouteGuide_method_names[2],
      ::grpc::RpcMethod::CLIENT_STREAMING,
      new ::grpc::ClientStreamingHandler< RouteGuide::Service, ::routeguide::Point, ::routeguide::RouteSummary>(
          std::mem_fn(&RouteGuide::Service::RecordRoute), this)));
  AddMethod(new ::grpc::RpcServiceMethod(
      RouteGuide_method_names[3],
      ::grpc::RpcMethod::BIDI_STREAMING,
      new ::grpc::BidiStreamingHandler< RouteGuide::Service, ::routeguide::RouteNote, ::routeguide::RouteNote>(
          std::mem_fn(&RouteGuide::Service::RouteChat), this)));
}

RouteGuide::Service::~Service() {
}

::grpc::Status RouteGuide::Service::GetFeature(::grpc::ServerContext* context, const ::routeguide::Point* request, ::routeguide::Feature* response) {
  (void) context;
  (void) request;
  (void) response;
  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
}

::grpc::Status RouteGuide::Service::ListFeatures(::grpc::ServerContext* context, const ::routeguide::Rectangle* request, ::grpc::ServerWriter< ::routeguide::Feature>* writer) {
  (void) context;
  (void) request;
  (void) writer;
  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
}

::grpc::Status RouteGuide::Service::RecordRoute(::grpc::ServerContext* context, ::grpc::ServerReader< ::routeguide::Point>* reader, ::routeguide::RouteSummary* response) {
  (void) context;
  (void) reader;
  (void) response;
  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
}

::grpc::Status RouteGuide::Service::RouteChat(::grpc::ServerContext* context, ::grpc::ServerReaderWriter< ::routeguide::RouteNote, ::routeguide::RouteNote>* stream) {
  (void) context;
  (void) stream;
  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
}


}  // namespace routeguide


创建服务器

  • 实现我们服务定义的生成的服务接口:做我们的服务的实际的“工作”。
  • 运行一个 gRPC 服务器,监听来自客户端的请求并返回服务的响应。
#include <algorithm>
#include <chrono>
#include <cmath>
#include <iostream>
#include <memory>
#include <string>

#include <grpc/grpc.h>
#include <grpcpp/server.h>
#include <grpcpp/server_builder.h>
#include <grpcpp/server_context.h>
#include <grpcpp/security/server_credentials.h>
#include "helper.h"
#ifdef BAZEL_BUILD
#include "examples/protos/route_guide.grpc.pb.h"
#else
#include "route_guide.grpc.pb.h"
#endif

using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::ServerReader;
using grpc::ServerReaderWriter;
using grpc::ServerWriter;
using grpc::Status;
using routeguide::Point;
using routeguide::Feature;
using routeguide::Rectangle;
using routeguide::RouteSummary;
using routeguide::RouteNote;
using routeguide::RouteGuide;
using std::chrono::system_clock;


float ConvertToRadians(float num) {
  return num * 3.1415926 /180;
}

// The formula is based on http://mathforum.org/library/drmath/view/51879.html
float GetDistance(const Point& start, const Point& end) {
  const float kCoordFactor = 10000000.0;
  float lat_1 = start.latitude() / kCoordFactor;
  float lat_2 = end.latitude() / kCoordFactor;
  float lon_1 = start.longitude() / kCoordFactor;
  float lon_2 = end.longitude() / kCoordFactor;
  float lat_rad_1 = ConvertToRadians(lat_1);
  float lat_rad_2 = ConvertToRadians(lat_2);
  float delta_lat_rad = ConvertToRadians(lat_2-lat_1);
  float delta_lon_rad = ConvertToRadians(lon_2-lon_1);

  float a = pow(sin(delta_lat_rad/2), 2) + cos(lat_rad_1) * cos(lat_rad_2) *
            pow(sin(delta_lon_rad/2), 2);
  float c = 2 * atan2(sqrt(a), sqrt(1-a));
  int R = 6371000; // metres

  return R * c;
}

std::string GetFeatureName(const Point& point,
                           const std::vector<Feature>& feature_list) {
  for (const Feature& f : feature_list) {
    if (f.location().latitude() == point.latitude() &&
        f.location().longitude() == point.longitude()) {
      return f.name();
    }
  }
  return "";
}

/* RouteGuideImpl实现了生成的 RouteGuide::Service 接口的类 */
class RouteGuideImpl final : public RouteGuide::Service {
 public:
  explicit RouteGuideImpl(const std::string& db) {
    routeguide::ParseDb(db, &feature_list_);
  }

  /*从客户端拿到一个 Point 然后将对应的特性返回给数据库中的 Feature,
  在这个方法中,我们用适当的信息填充 Feature,然后返回OK的状态,告诉 gRPC 我们已经处理完 RPC,并且 	Feature 可以返回给客户端。*/
  Status GetFeature(ServerContext* context, const Point* point,
                    Feature* feature) override {
    feature->set_name(GetFeatureName(*point, feature_list_));
    feature->mutable_location()->CopyFrom(*point);
    return Status::OK;
  }

	/*ListFeatures 是一个服务器端的流式 RPC,因此我们需要给客户端返回多个 Feature*/
  Status ListFeatures(ServerContext* context,
                      const routeguide::Rectangle* rectangle,
                      ServerWriter<Feature>* writer) override {
    auto lo = rectangle->lo();
    auto hi = rectangle->hi();
    long left = (std::min)(lo.longitude(), hi.longitude());
    long right = (std::max)(lo.longitude(), hi.longitude());
    long top = (std::max)(lo.latitude(), hi.latitude());
    long bottom = (std::min)(lo.latitude(), hi.latitude());
    for (const Feature& f : feature_list_) {
      if (f.location().longitude() >= left &&
          f.location().longitude() <= right &&
          f.location().latitude() >= bottom &&
          f.location().latitude() <= top) {
        writer->Write(f);
      }
    }
    return Status::OK;
  }

/*这次我们拿到的是一个ServerReader而不是请求对象和单一的响应。我们使用 ServerReader 的 Read() 方法去重复的往请求对象(在这个场景下是一个 Point)读取客户端的请求直到没有更多的消息:在每次调用后,服务器需要检查 Read() 的返回值。如果返回值为 true,流仍然存在,它就可以继续读取;如果返回值为 false,则表明消息流已经停止。*/
  Status RecordRoute(ServerContext* context, ServerReader<Point>* reader,
                     RouteSummary* summary) override {
    Point point;
    int point_count = 0;
    int feature_count = 0;
    float distance = 0.0;
    Point previous;

    system_clock::time_point start_time = system_clock::now();
    while (reader->Read(&point)) {
      point_count++;
      if (!GetFeatureName(point, feature_list_).empty()) {
        feature_count++;
      }
      if (point_count != 1) {
        distance += GetDistance(previous, point);
      }
      previous = point;
    }
    system_clock::time_point end_time = system_clock::now();
    summary->set_point_count(point_count);
    summary->set_feature_count(feature_count);
    summary->set_distance(static_cast<long>(distance));
    auto secs = std::chrono::duration_cast<std::chrono::seconds>(
        end_time - start_time);
    summary->set_elapsed_time(secs.count());

    return Status::OK;
  }

  Status RouteChat(ServerContext* context,
                   ServerReaderWriter<RouteNote, RouteNote>* stream) override {
    RouteNote note;
    while (stream->Read(&note)) {
      std::unique_lock<std::mutex> lock(mu_);
      for (const RouteNote& n : received_notes_) {
        if (n.location().latitude() == note.location().latitude() &&
            n.location().longitude() == note.location().longitude()) {
          stream->Write(n);
        }
      }
      received_notes_.push_back(note);
    }

    return Status::OK;
  }

 private:
  std::vector<Feature> feature_list_;
  std::mutex mu_;
  std::vector<RouteNote> received_notes_;
};

void RunServer(const std::string& db_path) {
  std::string server_address("0.0.0.0:50051");
  RouteGuideImpl service(db_path);

  ServerBuilder builder;
  builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
  builder.RegisterService(&service);
  std::unique_ptr<Server> server(builder.BuildAndStart());
  std::cout << "Server listening on " << server_address << std::endl;
  server->Wait();
}

int main(int argc, char** argv) {
  // Expect only arg: --db_path=path/to/route_guide_db.json.
  std::string db = routeguide::GetDbFileContent(argc, argv);
  RunServer(db);

  return 0;
}

创建客户端

#include <chrono>
#include <iostream>
#include <memory>
#include <random>
#include <string>
#include <thread>

#include <grpc/grpc.h>
#include <grpcpp/channel.h>
#include <grpcpp/client_context.h>
#include <grpcpp/create_channel.h>
#include <grpcpp/security/credentials.h>
#include "helper.h"
#ifdef BAZEL_BUILD
#include "examples/protos/route_guide.grpc.pb.h"
#else
#include "route_guide.grpc.pb.h"
#endif

using grpc::Channel;
using grpc::ClientContext;
using grpc::ClientReader;
using grpc::ClientReaderWriter;
using grpc::ClientWriter;
using grpc::Status;
using routeguide::Point;
using routeguide::Feature;
using routeguide::Rectangle;
using routeguide::RouteSummary;
using routeguide::RouteNote;
using routeguide::RouteGuide;

Point MakePoint(long latitude, long longitude) {
  Point p;
  p.set_latitude(latitude);
  p.set_longitude(longitude);
  return p;
}

Feature MakeFeature(const std::string& name,
                    long latitude, long longitude) {
  Feature f;
  f.set_name(name);
  f.mutable_location()->CopyFrom(MakePoint(latitude, longitude));
  return f;
}

RouteNote MakeRouteNote(const std::string& message,
                        long latitude, long longitude) {
  RouteNote n;
  n.set_message(message);
  n.mutable_location()->CopyFrom(MakePoint(latitude, longitude));
  return n;
}

class RouteGuideClient {
/*利用channel,使用从.proto中生成的RouteGuide类提供的NewStub方法去创建存根*/
 public:
  RouteGuideClient(std::shared_ptr<Channel> channel, const std::string& db)
      : stub_(RouteGuide::NewStub(channel)) {
    routeguide::ParseDb(db, &feature_list_);
  }

  void GetFeature() {
    Point point;
    Feature feature;
    point = MakePoint(409146138, -746188906);
    GetOneFeature(point, &feature);
    point = MakePoint(0, 0);
    GetOneFeature(point, &feature);
  }

  void ListFeatures() {
    routeguide::Rectangle rect;
    Feature feature;
    ClientContext context;

    rect.mutable_lo()->set_latitude(400000000);
    rect.mutable_lo()->set_longitude(-750000000);
    rect.mutable_hi()->set_latitude(420000000);
    rect.mutable_hi()->set_longitude(-730000000);
    std::cout << "Looking for features between 40, -75 and 42, -73"
              << std::endl;

    std::unique_ptr<ClientReader<Feature> > reader(
        stub_->ListFeatures(&context, rect));
    while (reader->Read(&feature)) {
      std::cout << "Found feature called "
                << feature.name() << " at "
                << feature.location().latitude()/kCoordFactor_ << ", "
                << feature.location().longitude()/kCoordFactor_ << std::endl;
    }
    Status status = reader->Finish();
    if (status.ok()) {
      std::cout << "ListFeatures rpc succeeded." << std::endl;
    } else {
      std::cout << "ListFeatures rpc failed." << std::endl;
    }
  }

  void RecordRoute() {
    Point point;
    RouteSummary stats;
    ClientContext context;
    const int kPoints = 10;
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();

    std::default_random_engine generator(seed);
    std::uniform_int_distribution<int> feature_distribution(
        0, feature_list_.size() - 1);
    std::uniform_int_distribution<int> delay_distribution(
        500, 1500);

    std::unique_ptr<ClientWriter<Point> > writer(
        stub_->RecordRoute(&context, &stats));
    for (int i = 0; i < kPoints; i++) {
      const Feature& f = feature_list_[feature_distribution(generator)];
      std::cout << "Visiting point "
                << f.location().latitude()/kCoordFactor_ << ", "
                << f.location().longitude()/kCoordFactor_ << std::endl;
      if (!writer->Write(f.location())) {
        // Broken stream.
        break;
      }
      std::this_thread::sleep_for(std::chrono::milliseconds(
          delay_distribution(generator)));
    }
    writer->WritesDone();
    Status status = writer->Finish();
    if (status.ok()) {
      std::cout << "Finished trip with " << stats.point_count() << " points\n"
                << "Passed " << stats.feature_count() << " features\n"
                << "Travelled " << stats.distance() << " meters\n"
                << "It took " << stats.elapsed_time() << " seconds"
                << std::endl;
    } else {
      std::cout << "RecordRoute rpc failed." << std::endl;
    }
  }

  void RouteChat() {
    ClientContext context;

    std::shared_ptr<ClientReaderWriter<RouteNote, RouteNote> > stream(
        stub_->RouteChat(&context));

    std::thread writer([stream]() {
      std::vector<RouteNote> notes{
        MakeRouteNote("First message", 0, 0),
        MakeRouteNote("Second message", 0, 1),
        MakeRouteNote("Third message", 1, 0),
        MakeRouteNote("Fourth message", 0, 0)};
      for (const RouteNote& note : notes) {
        std::cout << "Sending message " << note.message()
                  << " at " << note.location().latitude() << ", "
                  << note.location().longitude() << std::endl;
        stream->Write(note);
      }
      stream->WritesDone();
    });

    RouteNote server_note;
    while (stream->Read(&server_note)) {
      std::cout << "Got message " << server_note.message()
                << " at " << server_note.location().latitude() << ", "
                << server_note.location().longitude() << std::endl;
    }
    writer.join();
    Status status = stream->Finish();
    if (!status.ok()) {
      std::cout << "RouteChat rpc failed." << std::endl;
    }
  }

 private:

  bool GetOneFeature(const Point& point, Feature* feature) {
    ClientContext context;
    Status status = stub_->GetFeature(&context, point, feature);
    if (!status.ok()) {
      std::cout << "GetFeature rpc failed." << std::endl;
      return false;
    }
    if (!feature->has_location()) {
      std::cout << "Server returns incomplete feature." << std::endl;
      return false;
    }
    if (feature->name().empty()) {
      std::cout << "Found no feature at "
                << feature->location().latitude()/kCoordFactor_ << ", "
                << feature->location().longitude()/kCoordFactor_ << std::endl;
    } else {
      std::cout << "Found feature called " << feature->name()  << " at "
                << feature->location().latitude()/kCoordFactor_ << ", "
                << feature->location().longitude()/kCoordFactor_ << std::endl;
    }
    return true;
  }

  const float kCoordFactor_ = 10000000.0;
  std::unique_ptr<RouteGuide::Stub> stub_;
  std::vector<Feature> feature_list_;
};

int main(int argc, char** argv) {
  // Expect only arg: --db_path=path/to/route_guide_db.json.
  std::string db = routeguide::GetDbFileContent(argc, argv);
  /*为我们的存根创建一个gRPC channel,指定我们想连接的服务器地址和端口,以及 channel 相关的参数*/
  RouteGuideClient guide(
      grpc::CreateChannel("localhost:50051",
                          grpc::InsecureChannelCredentials()),
      db);

  std::cout << "-------------- GetFeature --------------" << std::endl;
  guide.GetFeature();
  std::cout << "-------------- ListFeatures --------------" << std::endl;
  guide.ListFeatures();
  std::cout << "-------------- RecordRoute --------------" << std::endl;
  guide.RecordRoute();
  std::cout << "-------------- RouteChat --------------" << std::endl;
  guide.RouteChat();

  return 0;
}

python

生成代码

安装grpc_python_plugin:

  • sudo pip3 install grpcio
 protoc -I . --python_out=. --grpc_out=. --plugin=protoc-gen-grpc=/usr/bin/grpc_python_plugin route_guide.proto

注: --plugin=protoc-gen-grpc='which grpc_python_plugin'没找到所以用指定路径

生成文件:

  • route_guide_pb2_grpc.py
  • route_guide_pb2.py
route_guide_pb2.py
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# source: route_guide.proto

import sys
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
from google.protobuf import descriptor_pb2
# @@protoc_insertion_point(imports)

_sym_db = _symbol_database.Default()




DESCRIPTOR = _descriptor.FileDescriptor(
  name='route_guide.proto',
  package='routeguide',
  syntax='proto3',
  serialized_pb=_b('\n\x11route_guide.proto\x12\nrouteguide\",\n\x05Point\x12\x10\n\x08latitude\x18\x01 \x01(\x05\x12\x11\n\tlongitude\x18\x02 \x01(\x05\"I\n\tRectangle\x12\x1d\n\x02lo\x18\x01 \x01(\x0b\x32\x11.routeguide.Point\x12\x1d\n\x02hi\x18\x02 \x01(\x0b\x32\x11.routeguide.Point\"<\n\x07\x46\x65\x61ture\x12\x0c\n\x04name\x18\x01 \x01(\t\x12#\n\x08location\x18\x02 \x01(\x0b\x32\x11.routeguide.Point\"A\n\tRouteNote\x12#\n\x08location\x18\x01 \x01(\x0b\x32\x11.routeguide.Point\x12\x0f\n\x07message\x18\x02 \x01(\t\"b\n\x0cRouteSummary\x12\x13\n\x0bpoint_count\x18\x01 \x01(\x05\x12\x15\n\rfeature_count\x18\x02 \x01(\x05\x12\x10\n\x08\x64istance\x18\x03 \x01(\x05\x12\x14\n\x0c\x65lapsed_time\x18\x04 \x01(\x05\x32\x85\x02\n\nRouteGuide\x12\x36\n\nGetFeature\x12\x11.routeguide.Point\x1a\x13.routeguide.Feature\"\x00\x12>\n\x0cListFeatures\x12\x15.routeguide.Rectangle\x1a\x13.routeguide.Feature\"\x00\x30\x01\x12>\n\x0bRecordRoute\x12\x11.routeguide.Point\x1a\x18.routeguide.RouteSummary\"\x00(\x01\x12?\n\tRouteChat\x12\x15.routeguide.RouteNote\x1a\x15.routeguide.RouteNote\"\x00(\x01\x30\x01\x42\x36\n\x1bio.grpc.examples.routeguideB\x0fRouteGuideProtoP\x01\xa2\x02\x03RTGb\x06proto3')
)
_sym_db.RegisterFileDescriptor(DESCRIPTOR)




_POINT = _descriptor.Descriptor(
  name='Point',
  full_name='routeguide.Point',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='latitude', full_name='routeguide.Point.latitude', index=0,
      number=1, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='longitude', full_name='routeguide.Point.longitude', index=1,
      number=2, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  syntax='proto3',
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=33,
  serialized_end=77,
)


_RECTANGLE = _descriptor.Descriptor(
  name='Rectangle',
  full_name='routeguide.Rectangle',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='lo', full_name='routeguide.Rectangle.lo', index=0,
      number=1, type=11, cpp_type=10, label=1,
      has_default_value=False, default_value=None,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='hi', full_name='routeguide.Rectangle.hi', index=1,
      number=2, type=11, cpp_type=10, label=1,
      has_default_value=False, default_value=None,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  syntax='proto3',
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=79,
  serialized_end=152,
)


_FEATURE = _descriptor.Descriptor(
  name='Feature',
  full_name='routeguide.Feature',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='name', full_name='routeguide.Feature.name', index=0,
      number=1, type=9, cpp_type=9, label=1,
      has_default_value=False, default_value=_b("").decode('utf-8'),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='location', full_name='routeguide.Feature.location', index=1,
      number=2, type=11, cpp_type=10, label=1,
      has_default_value=False, default_value=None,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  syntax='proto3',
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=154,
  serialized_end=214,
)


_ROUTENOTE = _descriptor.Descriptor(
  name='RouteNote',
  full_name='routeguide.RouteNote',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='location', full_name='routeguide.RouteNote.location', index=0,
      number=1, type=11, cpp_type=10, label=1,
      has_default_value=False, default_value=None,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='message', full_name='routeguide.RouteNote.message', index=1,
      number=2, type=9, cpp_type=9, label=1,
      has_default_value=False, default_value=_b("").decode('utf-8'),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  syntax='proto3',
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=216,
  serialized_end=281,
)


_ROUTESUMMARY = _descriptor.Descriptor(
  name='RouteSummary',
  full_name='routeguide.RouteSummary',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='point_count', full_name='routeguide.RouteSummary.point_count', index=0,
      number=1, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='feature_count', full_name='routeguide.RouteSummary.feature_count', index=1,
      number=2, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='distance', full_name='routeguide.RouteSummary.distance', index=2,
      number=3, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='elapsed_time', full_name='routeguide.RouteSummary.elapsed_time', index=3,
      number=4, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  syntax='proto3',
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=283,
  serialized_end=381,
)

_RECTANGLE.fields_by_name['lo'].message_type = _POINT
_RECTANGLE.fields_by_name['hi'].message_type = _POINT
_FEATURE.fields_by_name['location'].message_type = _POINT
_ROUTENOTE.fields_by_name['location'].message_type = _POINT
DESCRIPTOR.message_types_by_name['Point'] = _POINT
DESCRIPTOR.message_types_by_name['Rectangle'] = _RECTANGLE
DESCRIPTOR.message_types_by_name['Feature'] = _FEATURE
DESCRIPTOR.message_types_by_name['RouteNote'] = _ROUTENOTE
DESCRIPTOR.message_types_by_name['RouteSummary'] = _ROUTESUMMARY

Point = _reflection.GeneratedProtocolMessageType('Point', (_message.Message,), dict(
  DESCRIPTOR = _POINT,
  __module__ = 'route_guide_pb2'
  # @@protoc_insertion_point(class_scope:routeguide.Point)
  ))
_sym_db.RegisterMessage(Point)

Rectangle = _reflection.GeneratedProtocolMessageType('Rectangle', (_message.Message,), dict(
  DESCRIPTOR = _RECTANGLE,
  __module__ = 'route_guide_pb2'
  # @@protoc_insertion_point(class_scope:routeguide.Rectangle)
  ))
_sym_db.RegisterMessage(Rectangle)

Feature = _reflection.GeneratedProtocolMessageType('Feature', (_message.Message,), dict(
  DESCRIPTOR = _FEATURE,
  __module__ = 'route_guide_pb2'
  # @@protoc_insertion_point(class_scope:routeguide.Feature)
  ))
_sym_db.RegisterMessage(Feature)

RouteNote = _reflection.GeneratedProtocolMessageType('RouteNote', (_message.Message,), dict(
  DESCRIPTOR = _ROUTENOTE,
  __module__ = 'route_guide_pb2'
  # @@protoc_insertion_point(class_scope:routeguide.RouteNote)
  ))
_sym_db.RegisterMessage(RouteNote)

RouteSummary = _reflection.GeneratedProtocolMessageType('RouteSummary', (_message.Message,), dict(
  DESCRIPTOR = _ROUTESUMMARY,
  __module__ = 'route_guide_pb2'
  # @@protoc_insertion_point(class_scope:routeguide.RouteSummary)
  ))
_sym_db.RegisterMessage(RouteSummary)


DESCRIPTOR.has_options = True
DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.routeguideB\017RouteGuideProtoP\001\242\002\003RTG'))
try:
  # THESE ELEMENTS WILL BE DEPRECATED.
  # Please use the generated *_pb2_grpc.py files instead.
  import grpc
  from grpc.beta import implementations as beta_implementations
  from grpc.beta import interfaces as beta_interfaces
  from grpc.framework.common import cardinality
  from grpc.framework.interfaces.face import utilities as face_utilities


  class RouteGuideStub(object):
    """Interface exported by the server.
    """

    def __init__(self, channel):
      """Constructor.

      Args:
        channel: A grpc.Channel.
      """
      self.GetFeature = channel.unary_unary(
          '/routeguide.RouteGuide/GetFeature',
          request_serializer=Point.SerializeToString,
          response_deserializer=Feature.FromString,
          )
      self.ListFeatures = channel.unary_stream(
          '/routeguide.RouteGuide/ListFeatures',
          request_serializer=Rectangle.SerializeToString,
          response_deserializer=Feature.FromString,
          )
      self.RecordRoute = channel.stream_unary(
          '/routeguide.RouteGuide/RecordRoute',
          request_serializer=Point.SerializeToString,
          response_deserializer=RouteSummary.FromString,
          )
      self.RouteChat = channel.stream_stream(
          '/routeguide.RouteGuide/RouteChat',
          request_serializer=RouteNote.SerializeToString,
          response_deserializer=RouteNote.FromString,
          )


  class RouteGuideServicer(object):
    """Interface exported by the server.
    """

    def GetFeature(self, request, context):
      """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.
      """
      context.set_code(grpc.StatusCode.UNIMPLEMENTED)
      context.set_details('Method not implemented!')
      raise NotImplementedError('Method not implemented!')

    def ListFeatures(self, request, context):
      """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.
      """
      context.set_code(grpc.StatusCode.UNIMPLEMENTED)
      context.set_details('Method not implemented!')
      raise NotImplementedError('Method not implemented!')

    def RecordRoute(self, request_iterator, context):
      """A client-to-server streaming RPC.

      Accepts a stream of Points on a route being traversed, returning a
      RouteSummary when traversal is completed.
      """
      context.set_code(grpc.StatusCode.UNIMPLEMENTED)
      context.set_details('Method not implemented!')
      raise NotImplementedError('Method not implemented!')

    def RouteChat(self, request_iterator, context):
      """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).
      """
      context.set_code(grpc.StatusCode.UNIMPLEMENTED)
      context.set_details('Method not implemented!')
      raise NotImplementedError('Method not implemented!')


  def add_RouteGuideServicer_to_server(servicer, server):
    rpc_method_handlers = {
        'GetFeature': grpc.unary_unary_rpc_method_handler(
            servicer.GetFeature,
            request_deserializer=Point.FromString,
            response_serializer=Feature.SerializeToString,
        ),
        'ListFeatures': grpc.unary_stream_rpc_method_handler(
            servicer.ListFeatures,
            request_deserializer=Rectangle.FromString,
            response_serializer=Feature.SerializeToString,
        ),
        'RecordRoute': grpc.stream_unary_rpc_method_handler(
            servicer.RecordRoute,
            request_deserializer=Point.FromString,
            response_serializer=RouteSummary.SerializeToString,
        ),
        'RouteChat': grpc.stream_stream_rpc_method_handler(
            servicer.RouteChat,
            request_deserializer=RouteNote.FromString,
            response_serializer=RouteNote.SerializeToString,
        ),
    }
    generic_handler = grpc.method_handlers_generic_handler(
        'routeguide.RouteGuide', rpc_method_handlers)
    server.add_generic_rpc_handlers((generic_handler,))


  class BetaRouteGuideServicer(object):
    """The Beta API is deprecated for 0.15.0 and later.

    It is recommended to use the GA API (classes and functions in this
    file not marked beta) for all further purposes. This class was generated
    only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0."""
    """Interface exported by the server.
    """
    def GetFeature(self, request, context):
      """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.
      """
      context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
    def ListFeatures(self, request, context):
      """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.
      """
      context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
    def RecordRoute(self, request_iterator, context):
      """A client-to-server streaming RPC.

      Accepts a stream of Points on a route being traversed, returning a
      RouteSummary when traversal is completed.
      """
      context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
    def RouteChat(self, request_iterator, context):
      """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).
      """
      context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)


  class BetaRouteGuideStub(object):
    """The Beta API is deprecated for 0.15.0 and later.

    It is recommended to use the GA API (classes and functions in this
    file not marked beta) for all further purposes. This class was generated
    only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0."""
    """Interface exported by the server.
    """
    def GetFeature(self, request, timeout, metadata=None, with_call=False, protocol_options=None):
      """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.
      """
      raise NotImplementedError()
    GetFeature.future = None
    def ListFeatures(self, request, timeout, metadata=None, with_call=False, protocol_options=None):
      """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.
      """
      raise NotImplementedError()
    def RecordRoute(self, request_iterator, timeout, metadata=None, with_call=False, protocol_options=None):
      """A client-to-server streaming RPC.

      Accepts a stream of Points on a route being traversed, returning a
      RouteSummary when traversal is completed.
      """
      raise NotImplementedError()
    RecordRoute.future = None
    def RouteChat(self, request_iterator, timeout, metadata=None, with_call=False, protocol_options=None):
      """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).
      """
      raise NotImplementedError()


  def beta_create_RouteGuide_server(servicer, pool=None, pool_size=None, default_timeout=None, maximum_timeout=None):
    """The Beta API is deprecated for 0.15.0 and later.

    It is recommended to use the GA API (classes and functions in this
    file not marked beta) for all further purposes. This function was
    generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"""
    request_deserializers = {
      ('routeguide.RouteGuide', 'GetFeature'): Point.FromString,
      ('routeguide.RouteGuide', 'ListFeatures'): Rectangle.FromString,
      ('routeguide.RouteGuide', 'RecordRoute'): Point.FromString,
      ('routeguide.RouteGuide', 'RouteChat'): RouteNote.FromString,
    }
    response_serializers = {
      ('routeguide.RouteGuide', 'GetFeature'): Feature.SerializeToString,
      ('routeguide.RouteGuide', 'ListFeatures'): Feature.SerializeToString,
      ('routeguide.RouteGuide', 'RecordRoute'): RouteSummary.SerializeToString,
      ('routeguide.RouteGuide', 'RouteChat'): RouteNote.SerializeToString,
    }
    method_implementations = {
      ('routeguide.RouteGuide', 'GetFeature'): face_utilities.unary_unary_inline(servicer.GetFeature),
      ('routeguide.RouteGuide', 'ListFeatures'): face_utilities.unary_stream_inline(servicer.ListFeatures),
      ('routeguide.RouteGuide', 'RecordRoute'): face_utilities.stream_unary_inline(servicer.RecordRoute),
      ('routeguide.RouteGuide', 'RouteChat'): face_utilities.stream_stream_inline(servicer.RouteChat),
    }
    server_options = beta_implementations.server_options(request_deserializers=request_deserializers, response_serializers=response_serializers, thread_pool=pool, thread_pool_size=pool_size, default_timeout=default_timeout, maximum_timeout=maximum_timeout)
    return beta_implementations.server(method_implementations, options=server_options)


  def beta_create_RouteGuide_stub(channel, host=None, metadata_transformer=None, pool=None, pool_size=None):
    """The Beta API is deprecated for 0.15.0 and later.

    It is recommended to use the GA API (classes and functions in this
    file not marked beta) for all further purposes. This function was
    generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"""
    request_serializers = {
      ('routeguide.RouteGuide', 'GetFeature'): Point.SerializeToString,
      ('routeguide.RouteGuide', 'ListFeatures'): Rectangle.SerializeToString,
      ('routeguide.RouteGuide', 'RecordRoute'): Point.SerializeToString,
      ('routeguide.RouteGuide', 'RouteChat'): RouteNote.SerializeToString,
    }
    response_deserializers = {
      ('routeguide.RouteGuide', 'GetFeature'): Feature.FromString,
      ('routeguide.RouteGuide', 'ListFeatures'): Feature.FromString,
      ('routeguide.RouteGuide', 'RecordRoute'): RouteSummary.FromString,
      ('routeguide.RouteGuide', 'RouteChat'): RouteNote.FromString,
    }
    cardinalities = {
      'GetFeature': cardinality.Cardinality.UNARY_UNARY,
      'ListFeatures': cardinality.Cardinality.UNARY_STREAM,
      'RecordRoute': cardinality.Cardinality.STREAM_UNARY,
      'RouteChat': cardinality.Cardinality.STREAM_STREAM,
    }
    stub_options = beta_implementations.stub_options(host=host, metadata_transformer=metadata_transformer, request_serializers=request_serializers, response_deserializers=response_deserializers, thread_pool=pool, thread_pool_size=pool_size)
    return beta_implementations.dynamic_stub(channel, 'routeguide.RouteGuide', cardinalities, options=stub_options)
except ImportError:
  pass
# @@protoc_insertion_point(module_scope)

route_guide_pb2_grpc.py
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
import grpc

import route_guide_pb2 as route__guide__pb2


class RouteGuideStub(object):
  """Interface exported by the server.
  """

  def __init__(self, channel):
    """Constructor.

    Args:
      channel: A grpc.Channel.
    """
    self.GetFeature = channel.unary_unary(
        '/routeguide.RouteGuide/GetFeature',
        request_serializer=route__guide__pb2.Point.SerializeToString,
        response_deserializer=route__guide__pb2.Feature.FromString,
        )
    self.ListFeatures = channel.unary_stream(
        '/routeguide.RouteGuide/ListFeatures',
        request_serializer=route__guide__pb2.Rectangle.SerializeToString,
        response_deserializer=route__guide__pb2.Feature.FromString,
        )
    self.RecordRoute = channel.stream_unary(
        '/routeguide.RouteGuide/RecordRoute',
        request_serializer=route__guide__pb2.Point.SerializeToString,
        response_deserializer=route__guide__pb2.RouteSummary.FromString,
        )
    self.RouteChat = channel.stream_stream(
        '/routeguide.RouteGuide/RouteChat',
        request_serializer=route__guide__pb2.RouteNote.SerializeToString,
        response_deserializer=route__guide__pb2.RouteNote.FromString,
        )


class RouteGuideServicer(object):
  """Interface exported by the server.
  """

  def GetFeature(self, request, context):
    """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.
    """
    context.set_code(grpc.StatusCode.UNIMPLEMENTED)
    context.set_details('Method not implemented!')
    raise NotImplementedError('Method not implemented!')

  def ListFeatures(self, request, context):
    """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.
    """
    context.set_code(grpc.StatusCode.UNIMPLEMENTED)
    context.set_details('Method not implemented!')
    raise NotImplementedError('Method not implemented!')

  def RecordRoute(self, request_iterator, context):
    """A client-to-server streaming RPC.

    Accepts a stream of Points on a route being traversed, returning a
    RouteSummary when traversal is completed.
    """
    context.set_code(grpc.StatusCode.UNIMPLEMENTED)
    context.set_details('Method not implemented!')
    raise NotImplementedError('Method not implemented!')

  def RouteChat(self, request_iterator, context):
    """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).
    """
    context.set_code(grpc.StatusCode.UNIMPLEMENTED)
    context.set_details('Method not implemented!')
    raise NotImplementedError('Method not implemented!')


def add_RouteGuideServicer_to_server(servicer, server):
  rpc_method_handlers = {
      'GetFeature': grpc.unary_unary_rpc_method_handler(
          servicer.GetFeature,
          request_deserializer=route__guide__pb2.Point.FromString,
          response_serializer=route__guide__pb2.Feature.SerializeToString,
      ),
      'ListFeatures': grpc.unary_stream_rpc_method_handler(
          servicer.ListFeatures,
          request_deserializer=route__guide__pb2.Rectangle.FromString,
          response_serializer=route__guide__pb2.Feature.SerializeToString,
      ),
      'RecordRoute': grpc.stream_unary_rpc_method_handler(
          servicer.RecordRoute,
          request_deserializer=route__guide__pb2.Point.FromString,
          response_serializer=route__guide__pb2.RouteSummary.SerializeToString,
      ),
      'RouteChat': grpc.stream_stream_rpc_method_handler(
          servicer.RouteChat,
          request_deserializer=route__guide__pb2.RouteNote.FromString,
          response_serializer=route__guide__pb2.RouteNote.SerializeToString,
      ),
  }
  generic_handler = grpc.method_handlers_generic_handler(
      'routeguide.RouteGuide', rpc_method_handlers)
  server.add_generic_rpc_handlers((generic_handler,))

创建服务器

from concurrent import futures
import time
import math
import logging

import grpc

import route_guide_pb2
import route_guide_pb2_grpc
import route_guide_resources

_ONE_DAY_IN_SECONDS = 60 * 60 * 24


def get_feature(feature_db, point):
    """Returns Feature at given location or None."""
    for feature in feature_db:
        if feature.location == point:
            return feature
    return None


def get_distance(start, end):
    """Distance between two points."""
    coord_factor = 10000000.0
    lat_1 = start.latitude / coord_factor
    lat_2 = end.latitude / coord_factor
    lon_1 = start.longitude / coord_factor
    lon_2 = end.longitude / coord_factor
    lat_rad_1 = math.radians(lat_1)
    lat_rad_2 = math.radians(lat_2)
    delta_lat_rad = math.radians(lat_2 - lat_1)
    delta_lon_rad = math.radians(lon_2 - lon_1)

    # Formula is based on http://mathforum.org/library/drmath/view/51879.html
    a = (pow(math.sin(delta_lat_rad / 2), 2) +
         (math.cos(lat_rad_1) * math.cos(lat_rad_2) * pow(
             math.sin(delta_lon_rad / 2), 2)))
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
    R = 6371000
    # metres
    return R * c


class RouteGuideServicer(route_guide_pb2_grpc.RouteGuideServicer):
    """Provides methods that implement functionality of route guide server."""

    def __init__(self):
        self.db = route_guide_resources.read_route_guide_database()

    def GetFeature(self, request, context):
        feature = get_feature(self.db, request)
        if feature is None:
            return route_guide_pb2.Feature(name="", location=request)
        else:
            return feature

    def ListFeatures(self, request, context):
        left = min(request.lo.longitude, request.hi.longitude)
        right = max(request.lo.longitude, request.hi.longitude)
        top = max(request.lo.latitude, request.hi.latitude)
        bottom = min(request.lo.latitude, request.hi.latitude)
        for feature in self.db:
            if (feature.location.longitude >= left and
                    feature.location.longitude <= right and
                    feature.location.latitude >= bottom and
                    feature.location.latitude <= top):
                yield feature

    def RecordRoute(self, request_iterator, context):
        point_count = 0
        feature_count = 0
        distance = 0.0
        prev_point = None

        start_time = time.time()
        for point in request_iterator:
            point_count += 1
            if get_feature(self.db, point):
                feature_count += 1
            if prev_point:
                distance += get_distance(prev_point, point)
            prev_point = point

        elapsed_time = time.time() - start_time
        return route_guide_pb2.RouteSummary(
            point_count=point_count,
            feature_count=feature_count,
            distance=int(distance),
            elapsed_time=int(elapsed_time))

    def RouteChat(self, request_iterator, context):
        prev_notes = []
        for new_note in request_iterator:
            for prev_note in prev_notes:
                if prev_note.location == new_note.location:
                    yield prev_note
            prev_notes.append(new_note)


def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    route_guide_pb2_grpc.add_RouteGuideServicer_to_server(
        RouteGuideServicer(), server)
    server.add_insecure_port('[::]:50051')
    server.start()
    try:
        while True:
            time.sleep(_ONE_DAY_IN_SECONDS)
    except KeyboardInterrupt:
        server.stop(0)


if __name__ == '__main__':
    logging.basicConfig()
    serve()

创建客户端

from __future__ import print_function

import random
import logging

import grpc

import route_guide_pb2
import route_guide_pb2_grpc
import route_guide_resources


def make_route_note(message, latitude, longitude):
    return route_guide_pb2.RouteNote(
        message=message,
        location=route_guide_pb2.Point(latitude=latitude, longitude=longitude))


def guide_get_one_feature(stub, point):
    feature = stub.GetFeature(point)
    if not feature.location:
        print("Server returned incomplete feature")
        return

    if feature.name:
        print("Feature called %s at %s" % (feature.name, feature.location))
    else:
        print("Found no feature at %s" % feature.location)


def guide_get_feature(stub):
    guide_get_one_feature(stub,
                          route_guide_pb2.Point(
                              latitude=409146138, longitude=-746188906))
    guide_get_one_feature(stub, route_guide_pb2.Point(latitude=0, longitude=0))


def guide_list_features(stub):
    rectangle = route_guide_pb2.Rectangle(
        lo=route_guide_pb2.Point(latitude=400000000, longitude=-750000000),
        hi=route_guide_pb2.Point(latitude=420000000, longitude=-730000000))
    print("Looking for features between 40, -75 and 42, -73")

    features = stub.ListFeatures(rectangle)

    for feature in features:
        print("Feature called %s at %s" % (feature.name, feature.location))


def generate_route(feature_list):
    for _ in range(0, 10):
        random_feature = feature_list[random.randint(0, len(feature_list) - 1)]
        print("Visiting point %s" % random_feature.location)
        yield random_feature.location


def guide_record_route(stub):
    feature_list = route_guide_resources.read_route_guide_database()

    route_iterator = generate_route(feature_list)
    route_summary = stub.RecordRoute(route_iterator)
    print("Finished trip with %s points " % route_summary.point_count)
    print("Passed %s features " % route_summary.feature_count)
    print("Travelled %s meters " % route_summary.distance)
    print("It took %s seconds " % route_summary.elapsed_time)


def generate_messages():
    messages = [
        make_route_note("First message", 0, 0),
        make_route_note("Second message", 0, 1),
        make_route_note("Third message", 1, 0),
        make_route_note("Fourth message", 0, 0),
        make_route_note("Fifth message", 1, 0),
    ]
    for msg in messages:
        print("Sending %s at %s" % (msg.message, msg.location))
        yield msg


def guide_route_chat(stub):
    responses = stub.RouteChat(generate_messages())
    for response in responses:
        print("Received message %s at %s" % (response.message,
                                             response.location))


def run():
    # NOTE(gRPC Python Team): .close() is possible on a channel and should be
    # used in circumstances in which the with statement does not fit the needs
    # of the code.
    with grpc.insecure_channel('localhost:50051') as channel:
        stub = route_guide_pb2_grpc.RouteGuideStub(channel)
        print("-------------- GetFeature --------------")
        guide_get_feature(stub)
        print("-------------- ListFeatures --------------")
        guide_list_features(stub)
        print("-------------- RecordRoute --------------")
        guide_record_route(stub)
        print("-------------- RouteChat --------------")
        guide_route_chat(stub)


if __name__ == '__main__':
    logging.basicConfig()
    run()

go

https://blog.csdn.net/fwhezfwhez/article/details/90475510

生成客户端和服务器端代码

go get -u github.com/golang/protobuf/proto
go get -u github.com/golang/protobuf/protoc-gen-go

当Linux系统无法访问网络时:首先在github.com/golang/protobuf上或https://gitee.com/gooox/protobuf上下载protoc-gen-go和proto,(最好将其放在$GOPATH/src目录下)然后进入protoc-gen-go目录,执行go build、go install即可在$GOPATH/bin目录下发现这个工具。

 vim  /etc/profile 添加
    export GOPATH=/root/go
    export PATH=$PATH:$GOPATH/bin
source /etc/profile
// 错误protoc -I . --go_out=. route_guide.proto 这样生成的代码不完整只有protobuf没有grpc服务,正确的如下
protoc -I . route_guide.proto --go_out=plugins=grpc:route_guide
//route_guide是包含proto文件夹
上面也可以不修改环境变量,手动指定protoc-gen-go地址
protoc -I . route_guide.proto --go_out=plugins=grpc:./ --plugin=protoc-gen-go=/root/go/bin/protoc-gen-go

生成代码

route_guide.pb.go
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: route_guide.proto

package routeguide

import (
	context "context"
	fmt "fmt"
	proto "github.com/golang/protobuf/proto"
	grpc "google.golang.org/grpc"
	codes "google.golang.org/grpc/codes"
	status "google.golang.org/grpc/status"
	math "math"
)

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package

// 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).
type Point struct {
	Latitude             int32    `protobuf:"varint,1,opt,name=latitude,proto3" json:"latitude,omitempty"`
	Longitude            int32    `protobuf:"varint,2,opt,name=longitude,proto3" json:"longitude,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *Point) Reset()         { *m = Point{} }
func (m *Point) String() string { return proto.CompactTextString(m) }
func (*Point) ProtoMessage()    {}
func (*Point) Descriptor() ([]byte, []int) {
	return fileDescriptor_b7d679f20da65b7b, []int{0}
}

func (m *Point) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_Point.Unmarshal(m, b)
}
func (m *Point) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_Point.Marshal(b, m, deterministic)
}
func (m *Point) XXX_Merge(src proto.Message) {
	xxx_messageInfo_Point.Merge(m, src)
}
func (m *Point) XXX_Size() int {
	return xxx_messageInfo_Point.Size(m)
}
func (m *Point) XXX_DiscardUnknown() {
	xxx_messageInfo_Point.DiscardUnknown(m)
}

var xxx_messageInfo_Point proto.InternalMessageInfo

func (m *Point) GetLatitude() int32 {
	if m != nil {
		return m.Latitude
	}
	return 0
}

func (m *Point) GetLongitude() int32 {
	if m != nil {
		return m.Longitude
	}
	return 0
}

// A latitude-longitude rectangle, represented as two diagonally opposite
// points "lo" and "hi".
type Rectangle struct {
	// One corner of the rectangle.
	Lo *Point `protobuf:"bytes,1,opt,name=lo,proto3" json:"lo,omitempty"`
	// The other corner of the rectangle.
	Hi                   *Point   `protobuf:"bytes,2,opt,name=hi,proto3" json:"hi,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *Rectangle) Reset()         { *m = Rectangle{} }
func (m *Rectangle) String() string { return proto.CompactTextString(m) }
func (*Rectangle) ProtoMessage()    {}
func (*Rectangle) Descriptor() ([]byte, []int) {
	return fileDescriptor_b7d679f20da65b7b, []int{1}
}

func (m *Rectangle) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_Rectangle.Unmarshal(m, b)
}
func (m *Rectangle) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_Rectangle.Marshal(b, m, deterministic)
}
func (m *Rectangle) XXX_Merge(src proto.Message) {
	xxx_messageInfo_Rectangle.Merge(m, src)
}
func (m *Rectangle) XXX_Size() int {
	return xxx_messageInfo_Rectangle.Size(m)
}
func (m *Rectangle) XXX_DiscardUnknown() {
	xxx_messageInfo_Rectangle.DiscardUnknown(m)
}

var xxx_messageInfo_Rectangle proto.InternalMessageInfo

func (m *Rectangle) GetLo() *Point {
	if m != nil {
		return m.Lo
	}
	return nil
}

func (m *Rectangle) GetHi() *Point {
	if m != nil {
		return m.Hi
	}
	return nil
}

// A feature names something at a given point.
//
// If a feature could not be named, the name is empty.
type Feature struct {
	// The name of the feature.
	Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
	// The point where the feature is detected.
	Location             *Point   `protobuf:"bytes,2,opt,name=location,proto3" json:"location,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *Feature) Reset()         { *m = Feature{} }
func (m *Feature) String() string { return proto.CompactTextString(m) }
func (*Feature) ProtoMessage()    {}
func (*Feature) Descriptor() ([]byte, []int) {
	return fileDescriptor_b7d679f20da65b7b, []int{2}
}

func (m *Feature) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_Feature.Unmarshal(m, b)
}
func (m *Feature) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_Feature.Marshal(b, m, deterministic)
}
func (m *Feature) XXX_Merge(src proto.Message) {
	xxx_messageInfo_Feature.Merge(m, src)
}
func (m *Feature) XXX_Size() int {
	return xxx_messageInfo_Feature.Size(m)
}
func (m *Feature) XXX_DiscardUnknown() {
	xxx_messageInfo_Feature.DiscardUnknown(m)
}

var xxx_messageInfo_Feature proto.InternalMessageInfo

func (m *Feature) GetName() string {
	if m != nil {
		return m.Name
	}
	return ""
}

func (m *Feature) GetLocation() *Point {
	if m != nil {
		return m.Location
	}
	return nil
}

// A RouteNote is a message sent while at a given point.
type RouteNote struct {
	// The location from which the message is sent.
	Location *Point `protobuf:"bytes,1,opt,name=location,proto3" json:"location,omitempty"`
	// The message to be sent.
	Message              string   `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *RouteNote) Reset()         { *m = RouteNote{} }
func (m *RouteNote) String() string { return proto.CompactTextString(m) }
func (*RouteNote) ProtoMessage()    {}
func (*RouteNote) Descriptor() ([]byte, []int) {
	return fileDescriptor_b7d679f20da65b7b, []int{3}
}

func (m *RouteNote) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_RouteNote.Unmarshal(m, b)
}
func (m *RouteNote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_RouteNote.Marshal(b, m, deterministic)
}
func (m *RouteNote) XXX_Merge(src proto.Message) {
	xxx_messageInfo_RouteNote.Merge(m, src)
}
func (m *RouteNote) XXX_Size() int {
	return xxx_messageInfo_RouteNote.Size(m)
}
func (m *RouteNote) XXX_DiscardUnknown() {
	xxx_messageInfo_RouteNote.DiscardUnknown(m)
}

var xxx_messageInfo_RouteNote proto.InternalMessageInfo

func (m *RouteNote) GetLocation() *Point {
	if m != nil {
		return m.Location
	}
	return nil
}

func (m *RouteNote) GetMessage() string {
	if m != nil {
		return m.Message
	}
	return ""
}

// 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.
type RouteSummary struct {
	// The number of points received.
	PointCount int32 `protobuf:"varint,1,opt,name=point_count,json=pointCount,proto3" json:"point_count,omitempty"`
	// The number of known features passed while traversing the route.
	FeatureCount int32 `protobuf:"varint,2,opt,name=feature_count,json=featureCount,proto3" json:"feature_count,omitempty"`
	// The distance covered in metres.
	Distance int32 `protobuf:"varint,3,opt,name=distance,proto3" json:"distance,omitempty"`
	// The duration of the traversal in seconds.
	ElapsedTime          int32    `protobuf:"varint,4,opt,name=elapsed_time,json=elapsedTime,proto3" json:"elapsed_time,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *RouteSummary) Reset()         { *m = RouteSummary{} }
func (m *RouteSummary) String() string { return proto.CompactTextString(m) }
func (*RouteSummary) ProtoMessage()    {}
func (*RouteSummary) Descriptor() ([]byte, []int) {
	return fileDescriptor_b7d679f20da65b7b, []int{4}
}

func (m *RouteSummary) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_RouteSummary.Unmarshal(m, b)
}
func (m *RouteSummary) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_RouteSummary.Marshal(b, m, deterministic)
}
func (m *RouteSummary) XXX_Merge(src proto.Message) {
	xxx_messageInfo_RouteSummary.Merge(m, src)
}
func (m *RouteSummary) XXX_Size() int {
	return xxx_messageInfo_RouteSummary.Size(m)
}
func (m *RouteSummary) XXX_DiscardUnknown() {
	xxx_messageInfo_RouteSummary.DiscardUnknown(m)
}

var xxx_messageInfo_RouteSummary proto.InternalMessageInfo

func (m *RouteSummary) GetPointCount() int32 {
	if m != nil {
		return m.PointCount
	}
	return 0
}

func (m *RouteSummary) GetFeatureCount() int32 {
	if m != nil {
		return m.FeatureCount
	}
	return 0
}

func (m *RouteSummary) GetDistance() int32 {
	if m != nil {
		return m.Distance
	}
	return 0
}

func (m *RouteSummary) GetElapsedTime() int32 {
	if m != nil {
		return m.ElapsedTime
	}
	return 0
}

func init() {
	proto.RegisterType((*Point)(nil), "routeguide.Point")
	proto.RegisterType((*Rectangle)(nil), "routeguide.Rectangle")
	proto.RegisterType((*Feature)(nil), "routeguide.Feature")
	proto.RegisterType((*RouteNote)(nil), "routeguide.RouteNote")
	proto.RegisterType((*RouteSummary)(nil), "routeguide.RouteSummary")
}

func init() { proto.RegisterFile("route_guide.proto", fileDescriptor_b7d679f20da65b7b) }

var fileDescriptor_b7d679f20da65b7b = []byte{
	// 414 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x53, 0xdd, 0x8a, 0xd3, 0x40,
	0x14, 0xde, 0xc9, 0xee, 0xba, 0xcd, 0x49, 0x44, 0xf6, 0x88, 0x10, 0xa2, 0xa0, 0x1b, 0x6f, 0xf6,
	0xc6, 0xb0, 0xac, 0xb0, 0x97, 0x15, 0x5b, 0xb0, 0x37, 0x45, 0xea, 0xd8, 0xfb, 0x32, 0x26, 0xc7,
	0x74, 0x60, 0x92, 0x09, 0xc9, 0x04, 0xf4, 0x01, 0x7c, 0x02, 0xdf, 0xc0, 0x27, 0x95, 0x4c, 0x92,
	0x36, 0xd5, 0x96, 0xbd, 0x9b, 0xf3, 0x9d, 0xef, 0x3b, 0x3f, 0xdf, 0x61, 0xe0, 0xba, 0xd2, 0x8d,
	0xa1, 0x4d, 0xd6, 0xc8, 0x94, 0xe2, 0xb2, 0xd2, 0x46, 0x23, 0x58, 0xc8, 0x22, 0xd1, 0x47, 0xb8,
	0x5c, 0x69, 0x59, 0x18, 0x0c, 0x61, 0xa2, 0x84, 0x91, 0xa6, 0x49, 0x29, 0x60, 0x6f, 0xd8, 0xed,
	0x25, 0xdf, 0xc5, 0xf8, 0x0a, 0x5c, 0xa5, 0x8b, 0xac, 0x4b, 0x3a, 0x36, 0xb9, 0x07, 0xa2, 0x2f,
	0xe0, 0x72, 0x4a, 0x8c, 0x28, 0x32, 0x45, 0x78, 0x03, 0x8e, 0xd2, 0xb6, 0x80, 0x77, 0x7f, 0x1d,
	0xef, 0x1b, 0xc5, 0xb6, 0x0b, 0x77, 0x94, 0x6e, 0x29, 0x5b, 0x69, 0xcb, 0x1c, 0xa7, 0x6c, 0x65,
	0xb4, 0x84, 0xab, 0x4f, 0x24, 0x4c, 0x53, 0x11, 0x22, 0x5c, 0x14, 0x22, 0xef, 0x66, 0x72, 0xb9,
	0x7d, 0xe3, 0x3b, 0x98, 0x28, 0x9d, 0x08, 0x23, 0x75, 0x71, 0xba, 0xce, 0x8e, 0x12, 0xad, 0xc1,
	0xe5, 0x6d, 0xf6, 0xb3, 0x36, 0x87, 0x5a, 0xf6, 0xa8, 0x16, 0x03, 0xb8, 0xca, 0xa9, 0xae, 0x45,
	0xd6, 0x2d, 0xee, 0xf2, 0x21, 0x8c, 0x7e, 0x33, 0xf0, 0x6d, 0xd9, 0xaf, 0x4d, 0x9e, 0x8b, 0xea,
	0x27, 0xbe, 0x06, 0xaf, 0x6c, 0xd5, 0x9b, 0x44, 0x37, 0x85, 0xe9, 0x4d, 0x04, 0x0b, 0xcd, 0x5b,
	0x04, 0xdf, 0xc2, 0xd3, 0xef, 0xdd, 0x56, 0x3d, 0xa5, 0xb3, 0xd2, 0xef, 0xc1, 0x8e, 0x14, 0xc2,
	0x24, 0x95, 0xb5, 0x11, 0x45, 0x42, 0xc1, 0x79, 0x77, 0x87, 0x21, 0xc6, 0x1b, 0xf0, 0x49, 0x89,
	0xb2, 0xa6, 0x74, 0x63, 0x64, 0x4e, 0xc1, 0x85, 0xcd, 0x7b, 0x3d, 0xb6, 0x96, 0x39, 0xdd, 0xff,
	0x72, 0x00, 0xec, 0x54, 0x8b, 0x76, 0x1d, 0x7c, 0x00, 0x58, 0x90, 0x19, 0xbc, 0xfc, 0x7f, 0xd3,
	0xf0, 0xf9, 0x18, 0xea, 0x79, 0xd1, 0x19, 0x4e, 0xc1, 0x5f, 0xca, 0x7a, 0x10, 0xd6, 0xf8, 0x62,
	0x4c, 0xdb, 0x5d, 0xfb, 0x84, 0xfa, 0x8e, 0xe1, 0x14, 0x3c, 0x4e, 0x89, 0xae, 0x52, 0x3b, 0xcb,
	0xb1, 0xc6, 0xc1, 0x41, 0xc5, 0x91, 0x8f, 0xd1, 0xd9, 0x2d, 0xc3, 0x0f, 0xfd, 0xc9, 0xe6, 0x5b,
	0x61, 0xfe, 0x69, 0x3e, 0x5c, 0x32, 0x3c, 0x0e, 0xb7, 0xf2, 0x3b, 0x36, 0x7b, 0x80, 0x97, 0x52,
	0xc7, 0x59, 0x55, 0x26, 0x31, 0xfd, 0x10, 0x79, 0xa9, 0xa8, 0x1e, 0xd1, 0x67, 0xcf, 0xf6, 0x1e,
	0xad, 0xda, 0x3f, 0xb1, 0x62, 0x7f, 0x9c, 0x73, 0xbe, 0x5e, 0x7c, 0x7b, 0x62, 0xbf, 0xc8, 0xfb,
	0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xf3, 0xe2, 0x76, 0x5e, 0x37, 0x03, 0x00, 0x00,
}

// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn

// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4

// RouteGuideClient is the client API for RouteGuide service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type RouteGuideClient interface {
	// 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.
	GetFeature(ctx context.Context, in *Point, opts ...grpc.CallOption) (*Feature, error)
	// 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.
	ListFeatures(ctx context.Context, in *Rectangle, opts ...grpc.CallOption) (RouteGuide_ListFeaturesClient, error)
	// A client-to-server streaming RPC.
	//
	// Accepts a stream of Points on a route being traversed, returning a
	// RouteSummary when traversal is completed.
	RecordRoute(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RecordRouteClient, error)
	// 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).
	RouteChat(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RouteChatClient, error)
}

type routeGuideClient struct {
	cc *grpc.ClientConn
}

func NewRouteGuideClient(cc *grpc.ClientConn) RouteGuideClient {
	return &routeGuideClient{cc}
}

func (c *routeGuideClient) GetFeature(ctx context.Context, in *Point, opts ...grpc.CallOption) (*Feature, error) {
	out := new(Feature)
	err := c.cc.Invoke(ctx, "/routeguide.RouteGuide/GetFeature", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *routeGuideClient) ListFeatures(ctx context.Context, in *Rectangle, opts ...grpc.CallOption) (RouteGuide_ListFeaturesClient, error) {
	stream, err := c.cc.NewStream(ctx, &_RouteGuide_serviceDesc.Streams[0], "/routeguide.RouteGuide/ListFeatures", opts...)
	if err != nil {
		return nil, err
	}
	x := &routeGuideListFeaturesClient{stream}
	if err := x.ClientStream.SendMsg(in); err != nil {
		return nil, err
	}
	if err := x.ClientStream.CloseSend(); err != nil {
		return nil, err
	}
	return x, nil
}

type RouteGuide_ListFeaturesClient interface {
	Recv() (*Feature, error)
	grpc.ClientStream
}

type routeGuideListFeaturesClient struct {
	grpc.ClientStream
}

func (x *routeGuideListFeaturesClient) Recv() (*Feature, error) {
	m := new(Feature)
	if err := x.ClientStream.RecvMsg(m); err != nil {
		return nil, err
	}
	return m, nil
}

func (c *routeGuideClient) RecordRoute(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RecordRouteClient, error) {
	stream, err := c.cc.NewStream(ctx, &_RouteGuide_serviceDesc.Streams[1], "/routeguide.RouteGuide/RecordRoute", opts...)
	if err != nil {
		return nil, err
	}
	x := &routeGuideRecordRouteClient{stream}
	return x, nil
}

type RouteGuide_RecordRouteClient interface {
	Send(*Point) error
	CloseAndRecv() (*RouteSummary, error)
	grpc.ClientStream
}

type routeGuideRecordRouteClient struct {
	grpc.ClientStream
}

func (x *routeGuideRecordRouteClient) Send(m *Point) error {
	return x.ClientStream.SendMsg(m)
}

func (x *routeGuideRecordRouteClient) CloseAndRecv() (*RouteSummary, error) {
	if err := x.ClientStream.CloseSend(); err != nil {
		return nil, err
	}
	m := new(RouteSummary)
	if err := x.ClientStream.RecvMsg(m); err != nil {
		return nil, err
	}
	return m, nil
}

func (c *routeGuideClient) RouteChat(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RouteChatClient, error) {
	stream, err := c.cc.NewStream(ctx, &_RouteGuide_serviceDesc.Streams[2], "/routeguide.RouteGuide/RouteChat", opts...)
	if err != nil {
		return nil, err
	}
	x := &routeGuideRouteChatClient{stream}
	return x, nil
}

type RouteGuide_RouteChatClient interface {
	Send(*RouteNote) error
	Recv() (*RouteNote, error)
	grpc.ClientStream
}

type routeGuideRouteChatClient struct {
	grpc.ClientStream
}

func (x *routeGuideRouteChatClient) Send(m *RouteNote) error {
	return x.ClientStream.SendMsg(m)
}

func (x *routeGuideRouteChatClient) Recv() (*RouteNote, error) {
	m := new(RouteNote)
	if err := x.ClientStream.RecvMsg(m); err != nil {
		return nil, err
	}
	return m, nil
}

// RouteGuideServer is the server API for RouteGuide service.
type RouteGuideServer interface {
	// 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.
	GetFeature(context.Context, *Point) (*Feature, error)
	// 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.
	ListFeatures(*Rectangle, RouteGuide_ListFeaturesServer) error
	// A client-to-server streaming RPC.
	//
	// Accepts a stream of Points on a route being traversed, returning a
	// RouteSummary when traversal is completed.
	RecordRoute(RouteGuide_RecordRouteServer) error
	// 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).
	RouteChat(RouteGuide_RouteChatServer) error
}

// UnimplementedRouteGuideServer can be embedded to have forward compatible implementations.
type UnimplementedRouteGuideServer struct {
}

func (*UnimplementedRouteGuideServer) GetFeature(ctx context.Context, req *Point) (*Feature, error) {
	return nil, status.Errorf(codes.Unimplemented, "method GetFeature not implemented")
}
func (*UnimplementedRouteGuideServer) ListFeatures(req *Rectangle, srv RouteGuide_ListFeaturesServer) error {
	return status.Errorf(codes.Unimplemented, "method ListFeatures not implemented")
}
func (*UnimplementedRouteGuideServer) RecordRoute(srv RouteGuide_RecordRouteServer) error {
	return status.Errorf(codes.Unimplemented, "method RecordRoute not implemented")
}
func (*UnimplementedRouteGuideServer) RouteChat(srv RouteGuide_RouteChatServer) error {
	return status.Errorf(codes.Unimplemented, "method RouteChat not implemented")
}

func RegisterRouteGuideServer(s *grpc.Server, srv RouteGuideServer) {
	s.RegisterService(&_RouteGuide_serviceDesc, srv)
}

func _RouteGuide_GetFeature_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(Point)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(RouteGuideServer).GetFeature(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/routeguide.RouteGuide/GetFeature",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(RouteGuideServer).GetFeature(ctx, req.(*Point))
	}
	return interceptor(ctx, in, info, handler)
}

func _RouteGuide_ListFeatures_Handler(srv interface{}, stream grpc.ServerStream) error {
	m := new(Rectangle)
	if err := stream.RecvMsg(m); err != nil {
		return err
	}
	return srv.(RouteGuideServer).ListFeatures(m, &routeGuideListFeaturesServer{stream})
}

type RouteGuide_ListFeaturesServer interface {
	Send(*Feature) error
	grpc.ServerStream
}

type routeGuideListFeaturesServer struct {
	grpc.ServerStream
}

func (x *routeGuideListFeaturesServer) Send(m *Feature) error {
	return x.ServerStream.SendMsg(m)
}

func _RouteGuide_RecordRoute_Handler(srv interface{}, stream grpc.ServerStream) error {
	return srv.(RouteGuideServer).RecordRoute(&routeGuideRecordRouteServer{stream})
}

type RouteGuide_RecordRouteServer interface {
	SendAndClose(*RouteSummary) error
	Recv() (*Point, error)
	grpc.ServerStream
}

type routeGuideRecordRouteServer struct {
	grpc.ServerStream
}

func (x *routeGuideRecordRouteServer) SendAndClose(m *RouteSummary) error {
	return x.ServerStream.SendMsg(m)
}

func (x *routeGuideRecordRouteServer) Recv() (*Point, error) {
	m := new(Point)
	if err := x.ServerStream.RecvMsg(m); err != nil {
		return nil, err
	}
	return m, nil
}

func _RouteGuide_RouteChat_Handler(srv interface{}, stream grpc.ServerStream) error {
	return srv.(RouteGuideServer).RouteChat(&routeGuideRouteChatServer{stream})
}

type RouteGuide_RouteChatServer interface {
	Send(*RouteNote) error
	Recv() (*RouteNote, error)
	grpc.ServerStream
}

type routeGuideRouteChatServer struct {
	grpc.ServerStream
}

func (x *routeGuideRouteChatServer) Send(m *RouteNote) error {
	return x.ServerStream.SendMsg(m)
}

func (x *routeGuideRouteChatServer) Recv() (*RouteNote, error) {
	m := new(RouteNote)
	if err := x.ServerStream.RecvMsg(m); err != nil {
		return nil, err
	}
	return m, nil
}

var _RouteGuide_serviceDesc = grpc.ServiceDesc{
	ServiceName: "routeguide.RouteGuide",
	HandlerType: (*RouteGuideServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "GetFeature",
			Handler:    _RouteGuide_GetFeature_Handler,
		},
	},
	Streams: []grpc.StreamDesc{
		{
			StreamName:    "ListFeatures",
			Handler:       _RouteGuide_ListFeatures_Handler,
			ServerStreams: true,
		},
		{
			StreamName:    "RecordRoute",
			Handler:       _RouteGuide_RecordRoute_Handler,
			ClientStreams: true,
		},
		{
			StreamName:    "RouteChat",
			Handler:       _RouteGuide_RouteChat_Handler,
			ServerStreams: true,
			ClientStreams: true,
		},
	},
	Metadata: "route_guide.proto",
}

创建服务器

package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"math"
	"net"
	"sync"
	"time"

	"google.golang.org/grpc"

	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/testdata"

	"github.com/golang/protobuf/proto"

	pb "google.golang.org/grpc/examples/route_guide/routeguide"
)

var (
	tls        = flag.Bool("tls", false, "Connection uses TLS if true, else plain TCP")
	certFile   = flag.String("cert_file", "", "The TLS cert file")
	keyFile    = flag.String("key_file", "", "The TLS key file")
	jsonDBFile = flag.String("json_db_file", "", "A json file containing a list of features")
	port       = flag.Int("port", 10000, "The server port")
)

type routeGuideServer struct {
	savedFeatures []*pb.Feature // read-only after initialized

	mu         sync.Mutex // protects routeNotes
	routeNotes map[string][]*pb.RouteNote
}

// GetFeature returns the feature at the given point.
func (s *routeGuideServer) GetFeature(ctx context.Context, point *pb.Point) (*pb.Feature, error) {
	for _, feature := range s.savedFeatures {
		if proto.Equal(feature.Location, point) {
			return feature, nil
		}
	}
	// No feature was found, return an unnamed feature
	return &pb.Feature{Location: point}, nil
}

// ListFeatures lists all features contained within the given bounding Rectangle.
func (s *routeGuideServer) ListFeatures(rect *pb.Rectangle, stream pb.RouteGuide_ListFeaturesServer) error {
	for _, feature := range s.savedFeatures {
		if inRange(feature.Location, rect) {
			if err := stream.Send(feature); err != nil {
				return err
			}
		}
	}
	return nil
}

// RecordRoute records a route composited of a sequence of points.
//
// It 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.
func (s *routeGuideServer) RecordRoute(stream pb.RouteGuide_RecordRouteServer) error {
	var pointCount, featureCount, distance int32
	var lastPoint *pb.Point
	startTime := time.Now()
	for {
		point, err := stream.Recv()
		if err == io.EOF {
			endTime := time.Now()
			return stream.SendAndClose(&pb.RouteSummary{
				PointCount:   pointCount,
				FeatureCount: featureCount,
				Distance:     distance,
				ElapsedTime:  int32(endTime.Sub(startTime).Seconds()),
			})
		}
		if err != nil {
			return err
		}
		pointCount++
		for _, feature := range s.savedFeatures {
			if proto.Equal(feature.Location, point) {
				featureCount++
			}
		}
		if lastPoint != nil {
			distance += calcDistance(lastPoint, point)
		}
		lastPoint = point
	}
}

// RouteChat receives a stream of message/location pairs, and responds with a stream of all
// previous messages at each of those locations.
func (s *routeGuideServer) RouteChat(stream pb.RouteGuide_RouteChatServer) error {
	for {
		in, err := stream.Recv()
		if err == io.EOF {
			return nil
		}
		if err != nil {
			return err
		}
		key := serialize(in.Location)

		s.mu.Lock()
		s.routeNotes[key] = append(s.routeNotes[key], in)
		// Note: this copy prevents blocking other clients while serving this one.
		// We don't need to do a deep copy, because elements in the slice are
		// insert-only and never modified.
		rn := make([]*pb.RouteNote, len(s.routeNotes[key]))
		copy(rn, s.routeNotes[key])
		s.mu.Unlock()

		for _, note := range rn {
			if err := stream.Send(note); err != nil {
				return err
			}()
		}
	}
}

// loadFeatures loads features from a JSON file.
func (s *routeGuideServer) loadFeatures(filePath string) {
	var data []byte
	if filePath != "" {
		var err error
		data, err = ioutil.ReadFile(filePath)
		if err != nil {
			log.Fatalf("Failed to load default features: %v", err)
		}
	} else {
		data = exampleData
	}
	if err := json.Unmarshal(data, &s.savedFeatures); err != nil {
		log.Fatalf("Failed to load default features: %v", err)
	}
}

func toRadians(num float64) float64 {
	return num * math.Pi / float64(180)
}

// calcDistance calculates the distance between two points using the "haversine" formula.
// The formula is based on http://mathforum.org/library/drmath/view/51879.html.
func calcDistance(p1 *pb.Point, p2 *pb.Point) int32 {
	const CordFactor float64 = 1e7
	const R = float64(6371000) // earth radius in metres
	lat1 := toRadians(float64(p1.Latitude) / CordFactor)
	lat2 := toRadians(float64(p2.Latitude) / CordFactor)
	lng1 := toRadians(float64(p1.Longitude) / CordFactor)
	lng2 := toRadians(float64(p2.Longitude) / CordFactor)
	dlat := lat2 - lat1
	dlng := lng2 - lng1

	a := math.Sin(dlat/2)*math.Sin(dlat/2) +
		math.Cos(lat1)*math.Cos(lat2)*
			math.Sin(dlng/2)*math.Sin(dlng/2)
	c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))

	distance := R * c
	return int32(distance)
}

func inRange(point *pb.Point, rect *pb.Rectangle) bool {
	left := math.Min(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude))
	right := math.Max(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude))
	top := math.Max(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude))
	bottom := math.Min(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude))

	if float64(point.Longitude) >= left &&
		float64(point.Longitude) <= right &&
		float64(point.Latitude) >= bottom &&
		float64(point.Latitude) <= top {
		return true
	}
	return false
}

func serialize(point *pb.Point) string {
	return fmt.Sprintf("%d %d", point.Latitude, point.Longitude)
}

func newServer() *routeGuideServer {
	s := &routeGuideServer{routeNotes: make(map[string][]*pb.RouteNote)}
	s.loadFeatures(*jsonDBFile)
	return s
}

func main() {
	flag.Parse()
	lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", *port))
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	var opts []grpc.ServerOption
	if *tls {
		if *certFile == "" {
			*certFile = testdata.Path("server1.pem")
		}
		if *keyFile == "" {
			*keyFile = testdata.Path("server1.key")
		}
		creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile)
		if err != nil {
			log.Fatalf("Failed to generate credentials %v", err)
		}
		opts = []grpc.ServerOption{grpc.Creds(creds)}
	}
	grpcServer := grpc.NewServer(opts...)
	pb.RegisterRouteGuideServer(grpcServer, newServer())
	grpcServer.Serve(lis)
}

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

创建客户端

package main

import (
	"context"
	"flag"
	"io"
	"log"
	"math/rand"
	"time"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	pb "google.golang.org/grpc/examples/route_guide/routeguide"
	"google.golang.org/grpc/testdata"
)

var (
	tls                = flag.Bool("tls", false, "Connection uses TLS if true, else plain TCP")
	caFile             = flag.String("ca_file", "", "The file containing the CA root cert file")
	serverAddr         = flag.String("server_addr", "127.0.0.1:10000", "The server address in the format of host:port")
	serverHostOverride = flag.String("server_host_override", "x.test.youtube.com", "The server name use to verify the hostname returned by TLS handshake")
)

// printFeature gets the feature for the given point.
func printFeature(client pb.RouteGuideClient, point *pb.Point) {
	log.Printf("Getting feature for point (%d, %d)", point.Latitude, point.Longitude)
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	feature, err := client.GetFeature(ctx, point)
	if err != nil {
		log.Fatalf("%v.GetFeatures(_) = _, %v: ", client, err)
	}
	log.Println(feature)
}

// printFeatures lists all the features within the given bounding Rectangle.
func printFeatures(client pb.RouteGuideClient, rect *pb.Rectangle) {
	log.Printf("Looking for features within %v", rect)
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	stream, err := client.ListFeatures(ctx, rect)
	if err != nil {
		log.Fatalf("%v.ListFeatures(_) = _, %v", client, err)
	}
	for {
		feature, err := stream.Recv()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatalf("%v.ListFeatures(_) = _, %v", client, err)
		}
		log.Println(feature)
	}
}

// runRecordRoute sends a sequence of points to server and expects to get a RouteSummary from server.
func runRecordRoute(client pb.RouteGuideClient) {
	// Create a random number of random points
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	pointCount := int(r.Int31n(100)) + 2 // Traverse at least two points
	var points []*pb.Point
	for i := 0; i < pointCount; i++ {
		points = append(points, randomPoint(r))
	}
	log.Printf("Traversing %d points.", len(points))
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	stream, err := client.RecordRoute(ctx)
	if err != nil {
		log.Fatalf("%v.RecordRoute(_) = _, %v", client, err)
	}
	for _, point := range points {
		if err := stream.Send(point); err != nil {
			log.Fatalf("%v.Send(%v) = %v", stream, point, err)
		}
	}
	reply, err := stream.CloseAndRecv()
	if err != nil {
		log.Fatalf("%v.CloseAndRecv() got error %v, want %v", stream, err, nil)
	}
	log.Printf("Route summary: %v", reply)
}

// runRouteChat receives a sequence of route notes, while sending notes for various locations.
func runRouteChat(client pb.RouteGuideClient) {
	notes := []*pb.RouteNote{
		{Location: &pb.Point{Latitude: 0, Longitude: 1}, Message: "First message"},
		{Location: &pb.Point{Latitude: 0, Longitude: 2}, Message: "Second message"},
		{Location: &pb.Point{Latitude: 0, Longitude: 3}, Message: "Third message"},
		{Location: &pb.Point{Latitude: 0, Longitude: 1}, Message: "Fourth message"},
		{Location: &pb.Point{Latitude: 0, Longitude: 2}, Message: "Fifth message"},
		{Location: &pb.Point{Latitude: 0, Longitude: 3}, Message: "Sixth message"},
	}
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	stream, err := client.RouteChat(ctx)
	if err != nil {
		log.Fatalf("%v.RouteChat(_) = _, %v", client, err)
	}
	waitc := make(chan struct{})
	go func() {
		for {
			in, err := stream.Recv()
			if err == io.EOF {
				// read done.
				close(waitc)
				return
			}
			if err != nil {
				log.Fatalf("Failed to receive a note : %v", err)
			}
			log.Printf("Got message %s at point(%d, %d)", in.Message, in.Location.Latitude, in.Location.Longitude)
		}
	}()
	for _, note := range notes {
		if err := stream.Send(note); err != nil {
			log.Fatalf("Failed to send a note: %v", err)
		}
	}
	stream.CloseSend()
	<-waitc
}

func randomPoint(r *rand.Rand) *pb.Point {
	lat := (r.Int31n(180) - 90) * 1e7
	long := (r.Int31n(360) - 180) * 1e7
	return &pb.Point{Latitude: lat, Longitude: long}
}

func main() {
	flag.Parse()
	var opts []grpc.DialOption
	if *tls {
		if *caFile == "" {
			*caFile = testdata.Path("ca.pem")
		}
		creds, err := credentials.NewClientTLSFromFile(*caFile, *serverHostOverride)
		if err != nil {
			log.Fatalf("Failed to create TLS credentials %v", err)
		}
		opts = append(opts, grpc.WithTransportCredentials(creds))
	} else {
		opts = append(opts, grpc.WithInsecure())
	}
	conn, err := grpc.Dial(*serverAddr, opts...)
	if err != nil {
		log.Fatalf("fail to dial: %v", err)
	}
	defer conn.Close()
	client := pb.NewRouteGuideClient(conn)

	// Looking for a valid feature
	printFeature(client, &pb.Point{Latitude: 409146138, Longitude: -746188906})

	// Feature missing.
	printFeature(client, &pb.Point{Latitude: 0, Longitude: 0})

	// Looking for features between 40, -75 and 42, -73.
	printFeatures(client, &pb.Rectangle{
		Lo: &pb.Point{Latitude: 400000000, Longitude: -750000000},
		Hi: &pb.Point{Latitude: 420000000, Longitude: -730000000},
	})

	// RecordRoute
	runRecordRoute(client)

	// RouteChat
	runRouteChat(client)
}

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×