gRPC-04 客户端流的实现

19 篇文章 11 订阅

代码地址

https://github.com/wanmei002/grpc-learn/tree/master/ch03

客户端流的描述

在客户端流 RPC 模式中, 客户端会发送多个请求给服务器端,而不在是单个请求。服务端则会发送一个响应给客户端

clinet stream

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)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值