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

相关推荐
badhope4 小时前
Mobile-Skills:移动端技能可视化的创新实践
开发语言·人工智能·git·智能手机·github
码云数智-园园5 小时前
微服务架构下的分布式事务:在一致性与可用性之间寻找平衡
开发语言
疯狂吧小飞牛6 小时前
GPG基础指令
linux·服务器·网络
C++ 老炮儿的技术栈6 小时前
volatile使用场景
linux·服务器·c语言·开发语言·c++
hz_zhangrl6 小时前
CCF-GESP 等级考试 2026年3月认证C++一级真题解析
开发语言·c++·gesp·gesp2026年3月·gespc++一级
Liu628886 小时前
C++中的工厂模式高级应用
开发语言·c++·算法
IT猿手6 小时前
基于控制障碍函数的多无人机编队动态避障控制方法研究,MATLAB代码
开发语言·matlab·无人机·openclaw·多无人机动态避障路径规划·无人机编队
AI科技星6 小时前
全尺度角速度统一:基于 v ≡ c 的纯推导与验证
c语言·开发语言·人工智能·opencv·算法·机器学习·数据挖掘
hjxu20167 小时前
【OpenClaw 龙虾养成笔记一】在远程服务器,使用Docker安装OpenClaw
服务器·笔记·docker
sunwenjian8867 小时前
Java进阶——IO 流
java·开发语言·python