在以下场景使用unary rpc 可能有如下问题
stream rpc 适用于,大规模数据传递,和实时场景。
rpc SayHello(HelloRequest) returns (HelloResponse);
package main
import (
"context"
pb "d-grpc/lib/proto/hellowrold"
"google.golang.org/grpc"
"log"
)
const (
address = "localhost:50051"
)
func main() {
// 链接服务
conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
if err != nil {
log.Fatalf("dit not connetc:%v", err)
return
}
defer conn.Close()
// 创建一个客户端
c := pb.NewGreeterClient(conn)
r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: "world"})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
// 打印响应信息
log.Printf("Greeting: %s", r.GetMessage())
}
package main
import (
"context"
pb "d-grpc/lib/proto/hellowrold"
"google.golang.org/grpc"
"log"
"net"
)
const (
port = ":50051"
)
//
func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve:%v", err)
}
}
type server struct {
// 这个结构体实现了GreeterServer接口,避免service未实现
pb.UnimplementedGreeterServer
}
func (*server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
log.Printf("Received: %v", in.GetName())
return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
package main
import (
"context"
pb "d-grpc/lib/proto/echo"
"fmt"
"google.golang.org/grpc"
"log"
)
/*
1、客户端会写一个有效的数据到服务端,
2、客户端完成写的消息后,关闭发送,并等待接收消息
3、服务端读取消息,并返回响应消息
4、始终使用一个rpc请求来操作
*/
// 客户端流RPC
func main() {
clientCon, err := grpc.Dial("127.0.0.1:5001", grpc.WithInsecure(), grpc.WithBlock())
if err != nil {
log.Fatal(err)
}
clientStreamingEcho(pb.NewEchoClient(clientCon))
}
func clientStreamingEcho(client pb.EchoClient) {
stream, err := client.ClientStreamingEcho(context.Background())
if err != nil {
log.Fatal(err)
}
for i := 1; i < 10; i++ {
req := &pb.EchoRequest{
Message: fmt.Sprintf("%d", i),
}
// 会写成 有序的消息发送给给客户端
if err := stream.Send(req); err != nil {
log.Fatal(err)
}
}
// 关闭发送 并 接收数据, 让rpc知道我们客户端已经完成写的操作
resp, err := stream.CloseAndRecv()
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.GetMessage())
}
package main
import (
pb "d-grpc/lib/proto/echo"
"fmt"
"google.golang.org/grpc"
"io"
"log"
"net"
"strings"
)
func main() {
lis, err := net.Listen("tcp", "127.0.0.1:5001")
if err != nil {
log.Fatal(err)
}
s := grpc.NewServer()
pb.RegisterEchoServer(s, &server{})
if err := s.Serve(lis); err != nil {
log.Fatal(err)
}
}
type server struct {
pb.UnimplementedEchoServer
}
// https://grpc.io/docs/languages/go/basics/
func (server) ClientStreamingEcho(stream pb.Echo_ClientStreamingEchoServer) error {
// 循环读取客户端链接信息
var strList []string
for {
// 不断取得客户端请求数据
req, err := stream.Recv()
strList = append(strList, req.GetMessage())
// 代表客户端已经结束发送数据了
if err == io.EOF {
fmt.Println(strings.Join(strList, ","))
return stream.SendAndClose(&pb.EchoResponse{
Message: "已经全部接受完毕",
})
}
if err != nil {
return err
}
}
}
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
package main
import (
"context"
pb "d-grpc/lib/proto/echo"
"fmt"
"google.golang.org/grpc"
"io"
"log"
"strings"
)
/*
*/
func main() {
clientCon, err := grpc.Dial("127.0.0.1:5001", grpc.WithInsecure(), grpc.WithBlock())
if err != nil {
log.Fatal(err)
}
echoClient := pb.NewEchoClient(clientCon)
req := &pb.EchoRequest{}
stream, err := echoClient.ServerStreamingEcho(context.Background(), req)
if err != nil {
log.Fatal(err)
}
var strList []string
for {
resp, err := stream.Recv()
if err == nil {
strList = append(strList, resp.GetMessage())
}
if err == io.EOF {
fmt.Println(err)
break
}
if err != nil {
log.Println(err)
}
}
fmt.Println(strings.Join(strList, ","))
}
package main
import (
pb "d-grpc/lib/proto/echo"
"fmt"
"google.golang.org/grpc"
"log"
"net"
)
func main() {
lis, err := net.Listen("tcp", "127.0.0.1:5001")
if err != nil {
log.Fatal(err)
}
s := grpc.NewServer()
pb.RegisterEchoServer(s, &server{})
if err := s.Serve(lis); err != nil {
log.Fatal(err)
}
}
type server struct {
pb.UnimplementedEchoServer
}
func (server) ServerStreamingEcho(req *pb.EchoRequest, stream pb.Echo_ServerStreamingEchoServer) error {
// 向客户端发送数据
for i := 1; i < 10; i++ {
err := stream.Send(&pb.EchoResponse{
Message: fmt.Sprintf("%d", i),
})
if err != nil {
return err
}
}
// 返回 nil 或者 err就代表服务端响应数据完毕
return nil
}
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
package main
import (
"context"
pb "d-grpc/lib/proto/echo"
"fmt"
"google.golang.org/grpc"
"io"
"log"
)
// 客户端流RPC
func main() {
clientCon, err := grpc.Dial("127.0.0.1:5001", grpc.WithInsecure(), grpc.WithBlock())
if err != nil {
log.Fatal(err)
}
bidirectionalStreamingEcho(pb.NewEchoClient(clientCon))
}
func bidirectionalStreamingEcho(client pb.EchoClient) {
stream, err := client.BidirectionalStreamingEcho(context.Background())
if err != nil {
log.Fatal(err)
}
done := make(chan struct{})
// 异步读取服务端消息
go func() {
for {
resp, err := stream.Recv()
if err == io.EOF {
close(done)
return
}
if err != nil {
log.Fatal(err)
}
log.Printf("recv-server-%s", resp.GetMessage())
}
}()
// 想服务端发送消息
for i := 1; i < 10; i++ {
err := stream.Send(&pb.EchoRequest{
Message: fmt.Sprintf("%d", i),
})
if err != nil {
log.Fatal(err)
}
}
// 部分发送了-代表客户端的数据已经放完毕了
_ = stream.CloseSend()
// 服务端消息接受完毕,退出程序
<-done
}
package main
import (
pb "d-grpc/lib/proto/echo"
"fmt"
"google.golang.org/grpc"
"io"
"log"
"net"
)
func main() {
lis, err := net.Listen("tcp", "127.0.0.1:5001")
if err != nil {
log.Fatal(err)
}
s := grpc.NewServer()
pb.RegisterEchoServer(s, &server{})
if err := s.Serve(lis); err != nil {
log.Fatal(err)
}
}
type server struct {
pb.UnimplementedEchoServer
}
func (server) BidirectionalStreamingEcho(stream pb.Echo_BidirectionalStreamingEchoServer) error {
for {
req, err := stream.Recv()
if err == io.EOF {
return nil
}
if err != nil {
return err
}
log.Printf("recv-client-%s\n", req.GetMessage())
// 发送响应的数据
err = stream.Send(&pb.EchoResponse{
Message: fmt.Sprintf("server-%s", req.GetMessage()),
})
if err != nil {
return err
}
}
}