proto文件
syntax="proto3";
package services;
//用户模型
message UserInfo{
int32 user_id=1;
int32 user_score=2;
}
message UserScoreRequest{
repeated UserInfo users=1;
}
message UserScoreResponse{
repeated UserInfo users=1;
}
service UserService{
//服务流模式
rpc GetUserScoreByServerStream(UserScoreRequest) returns (stream UserScoreResponse);
//客户流模式
rpc GetUserScoreByClientStream(stream UserScoreRequest) returns (UserScoreResponse);
//双向流模式
rpc GetUserScoreByTWS(stream UserScoreRequest) returns (stream UserScoreResponse);
}
编译命令
protoc --go_out=plugins=grpc:../services Users.proto
一. 服务流模式。
- 实现方法
//服务端流模式
func(*UserService) GetUserScoreByServerStream(in *UserScoreRequest,stream UserService_GetUserScoreByServerStreamServer) error{
var score int32=101 //模拟分数
users:=make([]*UserInfo,0) //用户切片
//遍历传过来的用户切片
for index,user:=range in.Users{
user.UserScore=score //新增模拟分数属性
score++
users=append(users,user) //加到用户切片里面
//每两组发送一次
if (index+1) %2==0 && index>0{
err:=stream.Send(&UserScoreResponse{
Users:users})
if err!=nil{
return nil
}
users=(users)[0:0] //清空用户切片
}
}
return nil
}
- 客户端
//服务端流模式
func main(){
conn,err:=grpc.Dial(":8081",grpc.WithTransportCredentials(helper.GetClientCreds()))
if err!=nil{
log.Fatal(err)
}
defer conn.Close()
ctx:=context.Background()
userClient:=services.NewUserServiceClient(conn)
var i int32
req:=services.UserScoreRequest{
}
req.Users=make([]*services.UserInfo,0)
for i=1;i<=10;i++{
//加了5条用户信息
req.Users=append(req.Users,&services.UserInfo{
UserId:i})
}
stream,err:=userClient.GetUserScoreByServerStream(ctx,&req)
if err!=nil{
log.Fatal(err)
}
for{
//接收
res,err:=stream.Recv()
//接收完了
if err==io.EOF{
break
}
if err!=nil{
log.Fatal(err)
}
fmt.Println(res.Users)
}
}
- 结果
[user_id:1 user_score:101 user_id:2 user_score:102]
[user_id:3 user_score:103 user_id:4 user_score:104]
[user_id:5 user_score:105 user_id:6 user_score:106]
[user_id:7 user_score:107 user_id:8 user_score:108]
[user_id:9 user_score:109 user_id:10 user_score:110]
一. 服务流模式。
- 实现方法
//客户端流模式
func(*UserService) GetUserScoreByClientStream(stream UserService_GetUserScoreByClientStreamServer) error {
var score int32 = 101
users := make([]*UserInfo, 0)
for {
//接收
req, err := stream.Recv()
//接收完了返回结果并关闭
if err == io.EOF {
return stream.SendAndClose(&UserScoreResponse{
Users: users})
}
if err != nil {
return err
}
//接收user append到切片
for _, user := range req.Users {
user.UserScore = score
score++
users = append(users, user)
}
}
}
- 客户端
func main(){
conn,err:=grpc.Dial(":8081",grpc.WithTransportCredentials(helper.GetClientCreds()))
if err!=nil{
log.Fatal(err)
}
defer conn.Close()
ctx:=context.Background()
userClient:=services.NewUserServiceClient(conn)
var i int32
if err!=nil{
log.Fatal(err)
}
stream,err:=userClient.GetUserScoreByClientStream(ctx)
if err!=nil{
log.Fatal(err)
}
for j:=1;j<=3;j++{
req:=services.UserScoreRequest{
}
req.Users=make([]*services.UserInfo,0)
for i=1;i<=5;i++{
//加了5条用户信息 假设是一个耗时的过程
req.Users=append(req.Users,&services.UserInfo{
UserId:i})
}
err:=stream.Send(&req)
if err!=nil{
log.Println(err)
}
}
res,_:=stream.CloseAndRecv()
fmt.Println(res.Users)
}
- 结果
[user_id:1 user_score:101 user_id:2 user_score:102 user_id:3 user_score:103 user_id:4 user_score:104 user_id:5 user_score:105 user_id:1 use
r_score:106 user_id:2 user_score:107 user_id:3 user_score:108 user_id:4 user_score:109 user_id:5 user_score:110 user_id:1 user_score:111 us
er_id:2 user_score:112 user_id:3 user_score:113 user_id:4 user_score:114 user_id:5 user_score:115]
三. 双向流模式
- 实现方法
func(*UserService) GetUserScoreByTWS(stream UserService_GetUserScoreByTWSServer) error {
var score int32=101
users:=make([]*UserInfo,0)
for{
//接收
req,err:=stream.Recv()
if err==io.EOF{
//接收完了
return nil
}
if err!=nil{
return err
}
//遍历传过来的用户切片
for _,user:=range req.Users{
user.UserScore=score //这里好比是服务端做的业务处理
score++
users=append(users,user)
}
//发送
err=stream.Send(&UserScoreResponse{
Users:users})
if err!=nil{
log.Println(err)
}
//清空切片
users=(users)[0:0]
}
}
- 客户端
//双向流模式
func main(){
//creds, err := credentials.NewClientTLSFromFile("keys/server.crt", "localhost")
//if err != nil {
// log.Fatal(err)
//}
//创建连接
conn,err:=grpc.Dial(":8081",grpc.WithTransportCredentials(helper.GetClientCreds()))
if err!=nil{
log.Fatal(err)
}
defer conn.Close()
ctx:=context.Background()
//客户端
userClient:=services.NewUserServiceClient(conn)
var i int32
if err!=nil{
log.Fatal(err)
}
//调用方法
stream,err:=userClient.GetUserScoreByTWS(ctx)
if err!=nil{
log.Fatal(err)
}
var uid int32=1
//分段执行三次
for j:=1;j<=3;j++{
//请求模型
req:=services.UserScoreRequest{
}
req.Users=make([]*services.UserInfo,0)
for i=1;i<=5;i++{
//加5条用户信息 假设是一个耗时的过程
req.Users=append(req.Users,&services.UserInfo{
UserId:uid})
uid++
}
//发送
err:=stream.Send(&req)
if err!=nil{
log.Println(err)
}
//接收
res,err:=stream.Recv()
if err==io.EOF{
break
}
if err!=nil{
log.Println(err)
}
//打印
fmt.Println(res.Users)
}
//res,_:=stream.CloseAndRecv()
//fmt.Println(res.Users)
}
- 结果
[user_id:1 user_score:101 user_id:2 user_score:102 user_id:3 user_score:103 user_id:4 user_score:104 user_id:5 user_score:105 user_id:1 use
r_score:106 user_id:2 user_score:107 user_id:3 user_score:108 user_id:4 user_score:109 user_id:5 user_score:110 user_id:1 user_score:111 us
er_id:2 user_score:112 user_id:3 user_score:113 user_id:4 user_score:114 user_id:5 user_score:115]
服务端git地址: https://gitee.com/php_is_no1/gorpc.jtthink.com.git
客户端git地址:https://gitee.com/php_is_no1/gweb.jtthink.com.git