| /* | |
| * | |
| * 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. | |
| * | |
| */ | |
| // Package main implements a simple gRPC client that demonstrates how to use gRPC-Go libraries | |
| // to perform unary, client streaming, server streaming and full duplex RPCs. | |
| // | |
| // It interacts with the route guide service whose definition can be found in routeguide/route_guide.proto. | |
| package main | |
| import ( | |
| "context" | |
| "flag" | |
| "io" | |
| "log" | |
| rand "math/rand/v2" | |
| "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") | |
| ) | |
| // 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("client.GetFeature failed: %v", 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("client.ListFeatures failed: %v", err) | |
| } | |
| for { | |
| feature, err := stream.Recv() | |
| if err == io.EOF { | |
| break | |
| } | |
| if err != nil { | |
| log.Fatalf("client.ListFeatures failed: %v", err) | |
| } | |
| log.Printf("Feature: name: %q, point:(%v, %v)", feature.GetName(), | |
| feature.GetLocation().GetLatitude(), feature.GetLocation().GetLongitude()) | |
| } | |
| } | |
| // 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 | |
| pointCount := int(rand.Int32N(100)) + 2 // Traverse at least two points | |
| var points []*pb.Point | |
| for i := 0; i < pointCount; i++ { | |
| points = append(points, randomPoint()) | |
| } | |
| 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("client.RecordRoute failed: %v", err) | |
| } | |
| for _, point := range points { | |
| if err := stream.Send(point); err != nil { | |
| log.Fatalf("client.RecordRoute: stream.Send(%v) failed: %v", point, err) | |
| } | |
| } | |
| reply, err := stream.CloseAndRecv() | |
| if err != nil { | |
| log.Fatalf("client.RecordRoute failed: %v", err) | |
| } | |
| 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("client.RouteChat failed: %v", 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("client.RouteChat failed: %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("client.RouteChat: stream.Send(%v) failed: %v", note, err) | |
| } | |
| } | |
| stream.CloseSend() | |
| <-waitc | |
| } | |
| func randomPoint() *pb.Point { | |
| lat := (rand.Int32N(180) - 90) * 1e7 | |
| long := (rand.Int32N(360) - 180) * 1e7 | |
| return &pb.Point{Latitude: lat, Longitude: long} | |
| } | |
| func main() { | |
| flag.Parse() | |
| var opts []grpc.DialOption | |
| if *tls { | |
| if *caFile == "" { | |
| *caFile = data.Path("x509/ca_cert.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.WithTransportCredentials(insecure.NewCredentials())) | |
| } | |
| conn, err := grpc.NewClient(*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) | |
| } |