使用 protoc 指令產生出兩個檔案,這兩個檔案如何去實現Server端與Client端,當然也可以時作出Server端與Client使用不同的語言。
syntax = "proto3";
package NAME;
service ServiceName {
  rpc RPCName (stream ReqData) returns (stream ResData){}
}
message ReqData {
   string data = 1;
}
message ResData {
   string data = 1;
}
Server 基本使用
產出的grpc.pb.go中可以看到,需對於interface和struct要有一定的了解。
type ServiceNameServer interface {
	RPCName(ServiceNameServer_RPCNameServer) error
	mustEmbedUnimplementedServiceNameServer()
}
type UnimplementedServiceNameServer struct {
}
// ... 相關功能
type ServiceNameServer_RPCNameServer interface {
	Send(*ResData) error
	Recv() (*ReqData, error)
	grpc.ServerStream
}
func (*UnimplementedServiceNameServer) RPCName(ServiceNameServer_RPCNameServer) error {
	... // 系統自動生成功能 
}
server/main.go
package main
import (
	"go-grpc/pro"
	"google.golang.org/grpc"
)
// PORT port號
const PORT = ":50051"
type server struct {
	pro.UnimplementedServiceNameServer  // 將 grpc.pb.go 的 struct 註冊過來
}
func (s *server) RPCName(allStr pro.ServiceNameServer_RPCNameServer) error {
   // 處理 allStr.Recv() 和 處理 allStr.Send()
}
func main() {
	// 監聽口
	lis, err := net.Listen("tcp", PORT)
	if err != nil {
		return
	}
	// 建立一個 grpc 服務器
	s := grpc.NewServer()
	// 註冊事件
	pro.RegisterServiceServer(s, &server{})
	// 處理連結
	s.Serve(lis)
}
Client 基本使用
產出的grpc.pb.go中可以看到,需對於interface和struct要有一定的了解。
type ServiceNameClient interface {
	RPCName(ctx context.Context, opts ...grpc.CallOption) (ServiceName_RPCNameClient, error)
}
type serviceNameClient struct {
	cc grpc.ClientConnInterface
}
func (c *serviceNameClient) RPCName(ctx context.Context, opts ...grpc.CallOption) (ServiceName_RPCNameClient, error) {
	// ... 系統自動生成
	x := &serviceNameRPCNameClient{stream}
	return x, nil
}
type ServiceName_RPCNameClient interface {
	Send(*ReqData) error
	Recv() (*ResData, error)
	grpc.ClientStream
}
type serviceNameRPCNameClient struct {
	grpc.ClientStream
}
client/main.go
package main
import (
	"context"
	"google.golang.org/grpc"
	"go-grpc/pro"
	_ "google.golang.org/grpc/balancer/grpclb"
)
const (
	ADDRESS = "0.0.0.0:50051"
)
func main() {
	//建立 gRPC連線
	conn, err := grpc.Dial(ADDRESS, grpc.WithInsecure())
	if err != nil {
		return
	}
	defer conn.Close()
	//建立一個client。
	c := pro.NewServiceNameClient(conn)
	allStr, err := c.RPCName(context.Background())
	if err != nil {
		fmt.Println(err)
	}
	go func() {
		// data, err := allStr.Recv()
	}()
	go func() {
		// allStr.Send()
	}()
}
