1、获取gRPC

环境变量GOPATH的src目录下执行:

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文件

gRPC 允许定义4种类型的 service 方法。

(1)编写test.proto

syntax = "proto3";
package test; //参数
message Question{
string question_str = 1;
} //返回
message Answer{
string answer_str = 1;
} //定义服务
service Test{
//简单RPC
rpc GetAnswer1(Question) returns (Answer){}
//服务端流式RPC
rpc GetAnswer2(Question) returns (stream Answer){}
//客户端流式RPC
rpc GetAnswer3(stream Question) returns (Answer){}
//双向流式RPC
rpc GetAnswer4(stream Question) returns (stream Answer){}
}

(2)生成文件test.pb.go

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

3、服务端

package main

import (
"context"
"fmt"
"io"
"log"
"net"
"test/grpc/test" "google.golang.org/grpc"
) type testServer struct{} //简单RPC
//客户端一次请求,服务端一次响应
func (*testServer) GetAnswer1(ctx context.Context, q *test.Question) (*test.Answer, error) {
answer := test.Answer{AnswerStr: fmt.Sprintf("Question:%s;Answer:%s。", q.QuestionStr, "Answer1")}
return &answer, nil
} //服务端流式RPC
//客户端一次请求,服务端多次响应
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、客户端

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、输出

// 简单RPC===========================
// Question:问题11111111?;Answer:Answer1。
// 服务端流式RPC===========================
// Question:问题11111111?;Answer:Answer1。
// Question:问题11111111?;Answer:Answer2。
// Question:问题11111111?;Answer:Answer3。
// 客户端流式RPC===========================
// Question:问题1;Answer:Answer1。
// Question:问题2;Answer:Answer2。
// Question:问题3;Answer:Answer3。 // 双向流式RPC===============================
// Question:问题1;Answer:Answer1。
// Question:问题2;Answer:Answer2。
// Question:问题3;Answer:Answer3。
// Question:问题4;Answer:Answer4。

最新文章

  1. struts2工作流程
  2. js第三方
  3. 分享一些平时测试用的sql payloads
  4. Android drawableleft drawableTop 设置图片的大小
  5. ACCESS应用笔记&lt;五&gt;——慢慢要学会做项目管理&#183;
  6. Spring------概述
  7. CSS3-margin,padding,border
  8. Oracle执行语句跟踪(1)——使用sql trace实现语句追踪
  9. SQL Server 已提交读快照 测试
  10. 【BZOJ3160】万径人踪灭(FFT,Manacher)
  11. [总结]WEB前端常用命令
  12. ubuntu16.04配置anaconda环境
  13. python接口自动化测试(八)-unittest-生成测试报告
  14. acrgis导出成tiff图片,全是黑色
  15. (原创)拨开迷雾见月明-剖析asio中的proactor模式(二)
  16. salt之pillar组件
  17. 苹果电脑(Mac mini或Macbook或iMac)恢复出厂设置
  18. gym 100531 三维几何+搜索
  19. SQL语句200条(转)
  20. nmon 命令

热门文章

  1. Codeforces Round #649 (Div. 2) B. Most socially-distanced subsequence (数学,差分)
  2. Dapr 交通控制示例
  3. 买车交税 All In One
  4. TypeScript Generics All In one
  5. js 垃圾回收 &amp; js GC
  6. App Store Previewer
  7. AST &amp; js interpreter
  8. js &amp; class &amp; init
  9. 2021 NGK生态所体验好、交易快 引人注目!
  10. Renice INC:全球经济危机持续,2021年红酒市场走向如何?