流模式定义
由于要实现双向流,所以出参和入参都需要stream标识
syntax = "proto3";
option go_package = "./;streampb";
message StreamReqData{
string data = 1;
}
message StreamResData{
string data = 1;
}
//流需要stream 标识
service Greeter {
rpc AllStream(stream StreamReqData) returns (stream StreamResData);
}
代码生成
protoc -I . stream.proto --go_out=plugins=grpc:.
服务端实现
使用和一元rpc差不多,区别是入参(Greeter_AllStreamServer)提供了发送方法Send和接收方法Recv
入参的名称 = proto中 rpc服务名 + “_” + prc方法名 + server
package main
import (
streampb "Study/Six/pro"
"fmt"
"google.golang.org/grpc"
"net"
"time"
)
type service struct {
}
func (s *service) AllStream(stream streampb.Greeter_AllStreamServer) error {
var (
count int
)
for {
time.Sleep(time.Second)
count++
if res, err := stream.Recv(); err == nil {
fmt.Printf("收到客户端数据data:" + res.Data)
stream.Send(&streampb.StreamResData{
Data: fmt.Sprintf("服务端收到次数:%d", count),
})
}
}
return nil
}
func main() {
server := grpc.NewServer()
streampb.RegisterGreeterServer(server, &service{})
listen, _ := net.Listen("tcp", ":8088")
server.Serve(listen)
}
客户端实现
和一元rpc差不多,区别在于返回的参数提供了Send发送和Recv接收方法
package main
import (
streampb "Study/Six/pro"
"context"
"fmt"
"google.golang.org/grpc"
"sync"
"time"
)
func main() {
dial, _ := grpc.Dial(":8088", grpc.WithInsecure())
client := streampb.NewGreeterClient(dial)
stream, err := client.AllStream(context.Background())
if err != nil {
panic(err)
}
group := sync.WaitGroup{}
group.Add(2)
go func() {
for {
if recv, err := stream.Recv(); err == nil {
fmt.Println(fmt.Sprintf("接受到服务端返回数据DATA:%s", recv.Data))
}
}
group.Done()
}()
go func() {
count := 0
for {
time.Sleep(time.Second)
count++
stream.Send(&streampb.StreamReqData{
Data: fmt.Sprintf("服务端你好我的ID是%d \n", count),
})
}
}()
group.Wait()
}
执行结果