代码地址
https://github.com/wanmei002/grpc-learn/tree/master/ch03
客户端流的描述
在客户端流 RPC 模式中, 客户端会发送多个请求给服务器端,而不在是单个请求。服务端则会发送一个响应给客户端
proto 声明
service Product {
rpc SearchGoods (stream google.protobuf.StringValue) returns (OrderList);
}
message Order {
string id = 1;
repeated string items = 2;
string desc = 3;
}
message OrderList {
repeated Order list = 4;
}
服务端代码
实现 proto 文件声明的方法
func (s *server) SearchGoods(stream product.Product_SearchGoodsServer) error {
log.Println("start search goods")
var orderList product.OrderList
for {
orderKey, err := stream.Recv() // 接收流数据
if err != nil {
if err == io.EOF {// 接收到了客户端的结束信息
// 完成读取查询信息流
log.Println("recv over")
stream.SendAndClose(&orderList) // 返回proto文件里定义的返回值
return nil
}
log.Println("接收信息失败")
return err
}
// 对接收到的流数据 做逻辑处理
// 根据关键字 查询订单里是否有这个
time.Sleep(1e7)
log.Printf("recv 到的消息:%+v\n", orderKey)
for _, order := range AllOrderList {
for _, item := range order.Items {
if strings.Contains(item, orderKey.Value) {
orderList.List = append(orderList.List, &order)
break
}
}
}
}
}
main 方法代码
ls, err := net.Listen("tcp", ":8093")
if err != nil {
log.Println("server listen failed; err:", err)
return
}
g := grpc.NewServer()
product.RegisterProductServer(g, &server{})
fmt.Println("start server")
if err = g.Serve(ls); err != nil {
log.Println("server grpc serve failed; err:", err)
return
}
客户端代码实现
conn, err := grpc.Dial(":8093", grpc.WithInsecure())// grpc 拨号
if err != nil {
log.Println("client dial failed; err:", err)
return
}
defer conn.Close()
c := product.NewProductClient(conn)// 实例微服务的客户端
searchStream, err := c.SearchGoods(context.Background())
if err != nil {
log.Println("client search failed; err:", err)
return
}
// 查询订单
log.Println("search world")
// 发送流数据
if err := searchStream.Send(&wrappers.StringValue{Value: "world"}); err != nil {
log.Println("client send search value failed; value:", "world")
return
}
// 发送流数据
if err := searchStream.Send(&wrappers.StringValue{Value: "zyn"}); err != nil {
log.Println("client send search value failed; value:", "zyn")
return
}
// 结束流数据的发送 并获取请求
res, err := searchStream.CloseAndRecv()
if err != nil {
log.Println("client get result failed; err:", err)
return
}
fmt.Println("recv end")
fmt.Printf("res:%+v\n", res)