Golang GPRC流式传输案例

废话不多说,直接上代码:

1.项目目录结构
2.proto 代码
服务端server_stream.proto
Go 复制代码
syntax = "proto3";

package server;

// 包名
option go_package = "/server";

//定义rpc服务
service ServerStream {
  //定义函数体 主要stream
  rpc DownFile(ReqServer) returns (stream ResServer);
}

message ReqServer {
  string name = 1;
}

message ResServer {
  bytes content = 1;
}
客户端client_stream.proto
Go 复制代码
syntax = "proto3";

package client;

option go_package = "/client";

// 定义服务
service ClientStream {
  // 定义函数体 主要stream
  rpc UploadFile(stream ReqClient) returns (ResClient);
}

message ReqClient {
  string name    = 1;
  bytes  content = 2;
}

message ResClient {
  string name = 1;
}
3.客户端和服务端代码实现
客户端grpc_client_stream.go
Go 复制代码
package main

import (
	"bufio"
	"context"
	"fmt"
	"io"
	"log"
	"os"
	"project09/grpc/proto/stream/client"
	"project09/grpc/proto/stream/server"

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

func main() {
	addr := ":8010"
	// 创建一个客户端连接 且不使用安全证书来实现
	conn, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))

	if err != nil {
		log.Fatalf("grpc connect addr [%s] 连接失败%s", addr, err)
	}
	defer conn.Close()

	downFile(conn)

	uploadFile(conn)
}

func downFile(conn *grpc.ClientConn) {
	// 服务端流式 下载
	c := server.NewServerStreamClient(conn)
	stream, err := c.DownFile(context.Background(), &server.ReqServer{
		Name: "james",
	})
	if err != nil {
		return
	}
	file, err := os.OpenFile("./statics/down_music.mp4", os.O_CREATE|os.O_WRONLY, 0600)
	if err != nil {
		log.Fatalln(err)
	}
	defer file.Close()
	writer := bufio.NewWriter(file)
	for {
		response, e := stream.Recv()
		if e == io.EOF {
			break
		}
		writer.Write(response.Content)
	}
	writer.Flush()
	fmt.Println("客户端下载成功")
}

func uploadFile(conn *grpc.ClientConn) {
	// 客户端流式 上传
	s := client.NewClientStreamClient(conn)
	stream, err := s.UploadFile(context.Background())
	if err != nil {
		log.Fatalln(err)
	}
	file, err := os.Open("./statics/music.mp4")
	if err != nil {
		log.Fatalln(err)
	}
	defer file.Close()
	// 分片读取
	for {
		buf := make([]byte, 32)
		_, e := file.Read(buf)
		if e != nil {
			break
		}
		if e == io.EOF {
			break
		}
		stream.Send(&client.ReqClient{
			Content: buf,
		})
	}
	res, e2 := stream.CloseAndRecv()
	if e2 != nil {
		fmt.Println(res)
	}
	fmt.Println("客户端上传成功")
}
服务端grpc_server_stream.go
Go 复制代码
package main

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"project09/grpc/proto/stream/client"
	"project09/grpc/proto/stream/server"

	"google.golang.org/grpc"
)

type ServerStream struct {
}

func (s *ServerStream) DownFile(request *server.ReqServer, stream server.ServerStream_DownFileServer) error {
	fmt.Println("下载...")
	file, err := os.Open("./statics/music.mp4")
	if err != nil {
		log.Fatalln(err)
	}
	defer file.Close()
	// 分片读取
	for {
		buf := make([]byte, 32)
		_, err := file.Read(buf)
		if err != nil {
			break
		}
		if err == io.EOF {
			break
		}
		stream.Send(&server.ResServer{
			Content: buf,
		})
	}
	return nil
}

type ClientStream struct {
}

func (c *ClientStream) UploadFile(stream client.ClientStream_UploadFileServer) error {
	fmt.Println("上传...")
	file, err := os.OpenFile("./statics/upload_music.mp4", os.O_CREATE|os.O_WRONLY, 0600)
	if err != nil {
		log.Fatalln(err)
	}
	defer file.Close()
	writer := bufio.NewWriter(file)
	for {
		response, err := stream.Recv()
		if err == io.EOF {
			break
		}
		writer.Write(response.Content)
	}
	writer.Flush()

	stream.SendAndClose(&client.ResClient{
		Name: "上传完毕",
	})
	return nil
}

type BothStream struct {
}

func main() {
	listen, err := net.Listen("tcp", ":8010")
	if err != nil {
		fmt.Println("Fail to listen")
	}
	s := grpc.NewServer()
	// 将结构体注册为grpc服务
	server.RegisterServerStreamServer(s, &ServerStream{})
	client.RegisterClientStreamServer(s, &ClientStream{})

	fmt.Println("grpc stream server running :8010")
	// 开始处理客户端请求
	s.Serve(listen)
}

4.运行相关命令

proto生成编译的go文件
bash 复制代码
### 服务端流式
protoc -I . --go_out=plugins=grpc:./grpc/proto/stream .\grpc\proto\stream\server\server_stream.proto
### 客户端流式
protoc -I . --go_out=plugins=grpc:./grpc/proto/stream .\grpc\proto\stream\client\client_stream.proto
启动服务命令
bash 复制代码
## 服务端
go run .\grpc\server\stream\grpc_server_stream.go
## 客户端
go run .\grpc\client\stream\grpc_client_stream.go

以上案例是简单实现客户端流式传输和服务端流式传输,基于grpc性能调优,要根据自己的业务而定。

环境安装配置可参考上篇文章。《Golang Protoc Grpc实现微服务通信》

相关推荐
饺子大魔王的男人1 小时前
告别服务器失联!Prometheus+Alertmanager+cpolar 让监控告警不局限于内网
运维·服务器·prometheus
xyq20241 小时前
《C 经典100例》
开发语言
吉普赛的歌1 小时前
【服务器】为安全考虑,已锁定该用户帐户,原因是登录尝试或密码更。改尝试过多。请稍候片刻再重试,或与系统管理员或技术支持联系。
运维·服务器·安全
m0_737302581 小时前
腾讯云TDSQL-C+CVM软硬协同,数据库性能三倍跃升
服务器
不染尘.1 小时前
二分算法(优化)
开发语言·c++·算法
Fᴏʀ ʏ꯭ᴏ꯭ᴜ꯭.1 小时前
Keepalived高可用配置指南
服务器·网络·php
只是懒得想了1 小时前
Go语言ORM深度解析:GORM、XORM与entgo实战对比及最佳实践
开发语言·数据库·后端·golang
不吃橘子的橘猫1 小时前
Verilog HDL基础(概念+模块)
开发语言·学习·算法·fpga开发·verilog
掘根1 小时前
【jsonRpc项目】Registry-Discovery模块
运维·服务器·数据库