golang - gRPC learning

1, get gRPC

Execution environment variable GOPATH src directory:

git clone https://github.com/grpc/grpc-go.git google.golang.org/grpc

git clone https://github.com/golang/net.git golang.org/x/net

git clone https://github.com/golang/text.git golang.org/x/text

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

git clone https://github.com/google/go-genproto.git google.golang.org/genproto

go install google.golang.org/grpc

 2, proto file

gRPC allows to define four types of service method .

(1) write test.proto

= syntax "proto3"; 
Package Test; 

// Parameter 
Message {Question 
    String = question_str. 1; 
} 

// Returns 
Message {Answer The 
    String = answer_str. 1; 
} 

// define service 
-Service the Test { 
    // simply the RPC 
    RPC GetAnswer1 (Question) Returns (Answer The) {} 
    // server streaming the RPC 
    RPC GetAnswer2 (Question) Returns (Answer The stream) {} 
    // streaming client the RPC 
    RPC GetAnswer3 (Question stream) Returns (Answer The) {} 
    // bidirectional streaming the RPC 
    RPC GetAnswer4 (Question Stream) Returns (Answer The Stream) {} 
}

(2) generating a document test.pb.go

protoc --go_out=plugins=grpc:. test.proto

3, the server

main Package 

Import ( 
	"context" 
	"FMT" 
	"IO" 
	"log" 
	"NET" 
	"Test / GRPC / Test" 

	"google.golang.org/grpc" 
) 

type testServer struct {} 

// simply the RPC 
// a client request, the server response time 
FUNC (* testServer) GetAnswer1 (CTX context.Context, Q * test.Question) (test.Answer *, error) { 
	answer: = {AnswerStr test.Answer: fmt.Sprintf ( "Question:% S; answer The:.% S ", q.QuestionStr," answer1 ")} 
	return & answer, nil 
} 

// server streaming the RPC 
// a client request, the server response times 
func (* testServer) GetAnswer2 (q test.Question *, Stream test.Test_GetAnswer2Server) {error 
	for I: =. 1; I <=. 3; I ++ {
		answer := test.Answer{AnswerStr: fmt.Sprintf("Question:%s;Answer:%s%d。", q.QuestionStr, "Answer", i)}
		if err := stream.Send(&answer); err != nil {
			return err
		}
	}
	return nil
}

//客户端流式RPC
//客户端多次请求,服务端一次响应
func (*testServer) GetAnswer3(stream test.Test_GetAnswer3Server) error {
	answer := test.Answer{}
	for i := 1; ; i++ {
		question, err := stream.Recv()
		if err == io.EOF {
			return stream.SendAndClose(&answer)
		}
		if err != nil {
			return err
		}
		answer.AnswerStr = fmt.Sprintf("%sQuestion:%s;Answer:Answer%d。\n", answer.AnswerStr, question.QuestionStr, i)
	}
}

//双向流式RPC
//客户端多次请求,服务端多次响应
func (*testServer) GetAnswer4(stream test.Test_GetAnswer4Server) error {
	for i := 1; ; i++ {
		question, err := stream.Recv()
		if err == io.EOF {
			return nil
		}
		if err != nil {
			return err
		}
		answer := test.Answer{AnswerStr: fmt.Sprintf("Question:%s;Answer:%s%d。", question.QuestionStr, "Answer", i)}
		if err = stream.Send(&answer); err != nil {
			return err
		}
	}

}

func main() {
	lis, err := net.Listen("tcp", "127.0.0.1:5000")
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	grpcServer := grpc.NewServer()
	test.RegisterTestServer(grpcServer, &testServer{})
	grpcServer.Serve(lis)
}

4, the client

package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"test/grpc/test"

	"google.golang.org/grpc"
)

func main() {
	conn, err := grpc.Dial("127.0.0.1:5000", grpc.WithInsecure())
	if err != nil {
		log.Fatalf("fail to dial: %v", err)
	}
	defer conn.Close()
	client := test.NewTestClient(conn)

	fmt.Println("简单RPC===========================")
	question := test.Question{QuestionStr: "问题11111111?"}
	answer, err := client.GetAnswer1(context.Background(), &question)
	if err != nil {
		log.Fatalf("fail to GetAnswer1: %v", err)
	}
	fmt.Println(answer.AnswerStr)

	fmt.Println("服务端流式RPC===========================")
	stream, err := client.GetAnswer2(context.Background(), &question)
	if err != nil {
		log.Fatalf("fail to GetAnswer2: %v", err)
	}
	for {
		answer, err := stream.Recv()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatalf("%v.GetAnswer2, %v", client, err)
		}
		fmt.Println(answer.AnswerStr)
	}

	fmt.Println("客户端流式RPC===========================")
	stream3, err := client.GetAnswer3(context.Background())
	if err != nil {
		log.Fatalf("fail to GetAnswer3: %v", err)
	}
	for i := 1; i <= 3; i++ {
		question := test.Question{QuestionStr: fmt.Sprintf("问题%d", i)}
		if err = stream3.Send(&question); err != nil {
			log.Fatalf("fail to GetAnswer3 Send: %v", err)
		}
	}
	answer, err = stream3.CloseAndRecv()
	if err != nil {
		log.Fatalf("fail to GetAnswer3 CloseAndRecv: %v", err)
	}
	fmt.Println(answer.AnswerStr)

	fmt.Println("双向流式RPC===============================")
	done := make(chan bool)
	stream4, err := client.GetAnswer4(context.Background())
	if err != nil {
		log.Fatalf("fail to GetAnswer4: %v", err)
	}
	//接受服务端响应
	go func() {
		for {
			answer, err := stream4.Recv()
			if err == io.EOF {
				close(done)
				return
			}
			if err != nil {
				log.Fatalf("%v.GetAnswer4, %v", client, err)
			}
			fmt.Println(answer.AnswerStr)
		}
	}()
	//客户端发送请求
	for i := 1; i <= 4; i++ {
		question := test.Question{QuestionStr: fmt.Sprintf("问题%d", i)}
		if err = stream4.Send(&question); err != nil {
			log.Fatalf("fail to GetAnswer3 Send: %v", err)
		}
	}
	stream4.CloseSend()
	<-done
}

5, output

// =========================== simple RPC 
// Question: 11111111 problem? ; Answer: Answer1. 
// server streaming =========================== RPC 
// Question: 11111111 problem? ; Answer: Answer1. 
// Question: 11111111 problem? ; Answer: Answer2. 
// Question: 11111111 problem? ; Answer: Answer3. 
// client streaming =========================== RPC 
// Question: question 1; Answer: Answer1. 
// Question: question 2; Answer: Answer2. 
// Question: issue 3; Answer: Answer3. 

// bi-directional flow =============================== RPC 
// Question: question 1; Answer: Answer1. 
// Question: question 2; Answer: Answer2. 
// Question: issue 3; Answer: Answer3. 
// Question: question 4; Answer: Answer4.

Guess you like

Origin www.cnblogs.com/dzhy/p/11103429.html