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

相关推荐
Sinclair2 天前
简单几步,安卓手机秒变服务器,安装 CMS 程序
android·服务器
Rockbean3 天前
用40行代码搭建自己的无服务器OCR
服务器·python·deepseek
茶杯梦轩3 天前
CompletableFuture 在 项目实战 中 创建异步任务 的核心优势及使用场景
服务器·后端·面试
花酒锄作田4 天前
Gin 框架中的规范响应格式设计与实现
golang·gin
郑州光合科技余经理4 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
海天鹰4 天前
【免费】PHP主机=域名+解析+主机
服务器
feifeigo1234 天前
matlab画图工具
开发语言·matlab
dustcell.4 天前
haproxy七层代理
java·开发语言·前端
norlan_jame4 天前
C-PHY与D-PHY差异
c语言·开发语言
多恩Stone4 天前
【C++入门扫盲1】C++ 与 Python:类型、编译器/解释器与 CPU 的关系
开发语言·c++·人工智能·python·算法·3d·aigc