一,client.go 客户端主程序
主要内容在注释部分
package main
import (
"context"
"flag"
"io"
"log"
"math/rand"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/examples/data"
pb "google.golang.org/grpc/examples/route_guide/routeguide"
)
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("addr", "localhost:50051", "The server address in the format of host:port")
serverHostOverride = flag.String("server_host_override", "x.test.example.com", "The server name used to verify the hostname returned by the TLS handshake")
)
// 双端一元式
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)
}
// 服务端流式
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 {
// 从流中循环获取服务端写入的内容,直到末尾,Recv方法,在route_guide_grpc.pb.go中实现
feature, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
log.Fatalf("%v.ListFeatures(_) = _, %v", client, err)
}
log.Printf("Feature: name: %q, point:(%v, %v)", feature.GetName(),
feature.GetLocation().GetLatitude(), feature.GetLocation().GetLongitude())
}
}
// 客户端流式
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 {
// 多次往流中写入内容,Send方法,在route_guide_grpc.pb.go中实现
if err := stream.Send(point); err != nil {
log.Fatalf("%v.Send(%v) = %v", stream, point, err)
}
}
// 关闭流,并获取服务端的返回结果,CloseAndRecv方法,在route_guide_grpc.pb.go中实现
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)
}
// 双端双流式
func runRouteChat(client pb.RouteGuideClient) {
notes := []*pb.RouteNote{
{
Location: &pb.Point{
Latitude: 0, Longitude: 1}, Message: "First message"},</