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实现微服务通信》

相关推荐
人道领域13 分钟前
SSM框架从入门到入土(AOP面向切面编程)
java·开发语言
铅笔侠_小龙虾14 分钟前
Flutter 实战: 计算器
开发语言·javascript·flutter
2的n次方_32 分钟前
Runtime 执行提交机制:NPU 硬件队列的管理与任务原子化下发
c语言·开发语言
珠海西格电力科技40 分钟前
微电网能量平衡理论的实现条件在不同场景下有哪些差异?
运维·服务器·网络·人工智能·云计算·智慧城市
2501_944711431 小时前
JS 对象遍历全解析
开发语言·前端·javascript
释怀不想释怀1 小时前
Linux环境变量
linux·运维·服务器
zzzsde1 小时前
【Linux】进程(4):进程优先级&&调度队列
linux·运维·服务器
凡人叶枫1 小时前
C++中智能指针详解(Linux实战版)| 彻底解决内存泄漏,新手也能吃透
java·linux·c语言·开发语言·c++·嵌入式开发
Tony Bai1 小时前
再见,丑陋的 container/heap!Go 泛型堆 heap/v2 提案解析
开发语言·后端·golang
小糯米6012 小时前
C++顺序表和vector
开发语言·c++·算法