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

相关推荐
在繁华处4 小时前
Java从零到熟练(四):面向对象基础
java·开发语言
Unbelievabletobe4 小时前
解决了股票api接口盘后数据更新慢的问题
大数据·开发语言·python
不会C语言的男孩6 小时前
C++ Primer 第2章:变量和基本类型
开发语言·c++
在繁华处6 小时前
Java从零到熟练(三):流程控制
java·开发语言·python
tedcloud1236 小时前
DeepSeek-TUI部署教程:打造CLI AI助手环境
服务器·人工智能·word·excel·dreamweaver
无情的西瓜皮7 小时前
MCP协议实战:用Python从零搭建一个AI Agent工具服务器(保姆级教程)
服务器·人工智能·python·mcp
云泽8087 小时前
C++ 可调用对象通关指南:深度解析 Lambda 表达式、function 包装器与 bind 绑定器
开发语言·c++·算法
万能的知了7 小时前
服务器托管 vs 云主机 vs 裸金属:一个决策故事
运维·服务器·云计算
星恒随风8 小时前
Python 基础语法详解(一):从表达式、变量到数据类型
开发语言·笔记·python·学习
888CC++9 小时前
java 并发编程
java·开发语言·python