grpc---客户端流式

上一篇我们写了普通的grpc的调用过程,这篇接上篇写一下客户端流式 grpc

目录结构

在这里插入图片描述

protofile 目录是proto文件与生成go代码的命令proto.bat

product.proto

syntax  = "proto3";   //protobuf的版本
option go_package="../service";

package service;  //指定生成出来的 package

//定义request  model
message ProductRequest{
  int32 prod_id = 1;
}

//定义response model
message  ProductResponse{
  int32  prod_socket = 1;
}

service ProdService{
  //客户端流式传入
  rpc GetProdSocketSteamClient(stream ProductRequest)returns(ProductResponse);

}

proto.bat 命令

protoc --go_out=./ --go-grpc_out=./  .\product.proto
server目录写的是服务端接受客户端流式的业务逻辑
package main

import (
	"grpc-client-stream/service"
	"io"
	"log"
	"net"

	"google.golang.org/grpc"
)

type ProductService struct {
	*service.UnimplementedProdServiceServer
}

var productService = ProductService{}

/***********
接客户端流式发送的数据id   返回len后的id个数

服务端每收到一个message,保存其发送的ID,直到客户端关闭发送方向的流
Recv方法会一直阻塞直到从stream中接收到message,或者直到客户端调用CloseAndRecv方法
当客户端调用CloseAndRecv方法时,服务端调用Recv方法会得到io.EOF返回值
服务端调用SendAndClose方法发送响应message并关闭发送方向的流
***/
func (p ProductService) GetProdSocketSteamClient(stream service.ProdService_GetProdSocketSteamClientServer) error {
	log.Println("start of stream")
	var productRequest []*service.ProductRequest //切片准备
	//for循环开始接
	for {
		//接到的数据
		recv, err := stream.Recv()
		//数据接完了就跳出循环
		if err == io.EOF {
			log.Println("end of the recv direction of the stream")
			break
		}
		log.Printf("The name of user received is %s\n", recv.GetProdId())
		//将接到的数据塞到切片中
		productRequest = append(productRequest, recv)
	}
	//计算切片长度 并把int类型转化为int32
	i := int32(len(productRequest))
	log.Printf("send message about the prodIDSocket:%d ", i)
	//关闭结束
	err := stream.SendAndClose(&service.ProductResponse{ProdSocket: i})
	if err != nil {
		log.Panic(err)
	}
	log.Println("end of the send direction of the stream")
	return nil
}

func main() {
	// 创建socket监听器
	listener, _ := net.Listen("tcp", ":1234")
	// new一个gRPC服务器,用来注册服务
	grpcserver := grpc.NewServer()
	// 注册服务方法
	service.RegisterProdServiceServer(grpcserver, productService)
	// 开启gRPC服务
	_ = grpcserver.Serve(listener)
}
client目录是客户端向服务端流式发送并接受服务端的返回信息
package main

import (
	"context"
	"fmt"
	"grpc-client-stream/service"
	"log"
	"time"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
)

func main() {
	//建立无认证链接
	dial, err := grpc.Dial(":1234", grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		log.Fatal(err.Error())
	}
	defer dial.Close()
	//客户端实例化链接
	client := service.NewProdServiceClient(dial)
	//调用服务端方法
	steam, err := client.GetProdSocketSteamClient(context.Background())
	if err != nil {
		log.Fatal(err.Error())
	}

	for i := 0; i < 10; i++ {
		//向服务端发送流信息
		_ = steam.Send(&service.ProductRequest{ProdId: int32(i)})
		//等1秒
		time.Sleep(time.Second)
	}
	// 发送两次数据后主动关闭流并等待接收来自server端的message
	recv, err := steam.CloseAndRecv()
	if err != nil {
		log.Println(err)
	}
	fmt.Printf("The total  is %d", recv.GetProdSocket())
}

service目录是protobuf生成的文件

在这里插入图片描述

打开服务端的mian服务,再打开个命令行窗口打开客户端的main 进行请求就可以了

粗浅的理解,如果有什么不对的地方 请多多指教

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值