我用的是golang语言,所以后面的内容全是用golang表示的
syntax = "proto3";
package helloworld;
message UserInfo {
string name = 1;
string sex = 2;
int32 weight = 3;
}
message funcResponse {
string r_say = 1;
string r_name= 2;
string r_sex = 3;
}
service UserService {
rpc Login(UserInfo) returns (funcResponse){};
}
这里注意一点:syntax = "proto3"; 一定要放到文件的最开始的位置,否则会报错。
一种与语言无关的、平台无关的、可扩展的序列化结构化数据的方式,用于通信协议、数据存储等.
1,性能好,效率高
2,代码生成机制,数据解析类自动生成
3,支持向后兼容和向前兼容
4,支持多种编程语言(java,c++,python,golang等)
核心概念
1 .proto文件
相当于确定数据协议,数据结构中存在哪些数据,数据类型是怎么样
2 modifiers
2-1 required 不可以增加或删除的字段,必须初始化
2-2 optional 可选字段,可删除,可以不初始化
2-3 repeated 可重复字段, 对应到java文件里,生成的是List
3 Message
在proto文件里,数据的协议时以Message的形式表现的。
protoc -I=./ --go_out=plugins=grpc:./ ./service.proto 因为我用的是go所以最终生成的文件是:pbtest.pb.go
生成类似的文件:
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: pbtest.proto
/*
Package helloworld is a generated protocol buffer package.
It is generated from these files:
pbtest.proto
It has these top-level messages:
UserInfo
FuncResponse
*/
package helloworld
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type UserInfo struct {
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
Sex string `protobuf:"bytes,2,opt,name=sex" json:"sex,omitempty"`
Weight int32 `protobuf:"varint,3,opt,name=weight" json:"weight,omitempty"`
}
func (m *UserInfo) Reset() { *m = UserInfo{} }
func (m *UserInfo) String() string { return proto.CompactTextString(m) }
func (*UserInfo) ProtoMessage() {}
func (*UserInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *UserInfo) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *UserInfo) GetSex() string {
if m != nil {
return m.Sex
}
return ""
}
func (m *UserInfo) GetWeight() int32 {
if m != nil {
return m.Weight
}
return 0
}
type FuncResponse struct {
RSay string `protobuf:"bytes,1,opt,name=r_say,json=rSay" json:"r_say,omitempty"`
RName string `protobuf:"bytes,2,opt,name=r_name,json=rName" json:"r_name,omitempty"`
RSex string `protobuf:"bytes,3,opt,name=r_sex,json=rSex" json:"r_sex,omitempty"`
}
func (m *FuncResponse) Reset() { *m = FuncResponse{} }
func (m *FuncResponse) String() string { return proto.CompactTextString(m) }
func (*FuncResponse) ProtoMessage() {}
func (*FuncResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *FuncResponse) GetRSay() string {
if m != nil {
return m.RSay
}
return ""
}
func (m *FuncResponse) GetRName() string {
if m != nil {
return m.RName
}
return ""
}
func (m *FuncResponse) GetRSex() string {
if m != nil {
return m.RSex
}
return ""
}
func init() {
proto.RegisterType((*UserInfo)(nil), "helloworld.UserInfo")
proto.RegisterType((*FuncResponse)(nil), "helloworld.funcResponse")
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// Client API for UserService service
type UserServiceClient interface {
Login(ctx context.Context, in *UserInfo, opts ...grpc.CallOption) (*FuncResponse, error)
}
type userServiceClient struct {
cc *grpc.ClientConn
}
func NewUserServiceClient(cc *grpc.ClientConn) UserServiceClient {
return &userServiceClient{cc}
}
func (c *userServiceClient) Login(ctx context.Context, in *UserInfo, opts ...grpc.CallOption) (*FuncResponse, error) {
out := new(FuncResponse)
err := grpc.Invoke(ctx, "/helloworld.UserService/Login", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for UserService service
type UserServiceServer interface {
Login(context.Context, *UserInfo) (*FuncResponse, error)
}
func RegisterUserServiceServer(s *grpc.Server, srv UserServiceServer) {
s.RegisterService(&_UserService_serviceDesc, srv)
}
func _UserService_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UserInfo)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UserServiceServer).Login(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/helloworld.UserService/Login",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UserServiceServer).Login(ctx, req.(*UserInfo))
}
return interceptor(ctx, in, info, handler)
}
var _UserService_serviceDesc = grpc.ServiceDesc{
ServiceName: "helloworld.UserService",
HandlerType: (*UserServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Login",
Handler: _UserService_Login_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "pbtest.proto",
}
func init() { proto.RegisterFile("pbtest.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 209 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x4c, 0x8f, 0x4f, 0x4b, 0x85, 0x40,
0x14, 0xc5, 0xb3, 0xd7, 0x48, 0xdd, 0xde, 0x22, 0x6e, 0x7f, 0x18, 0x5a, 0x89, 0x2b, 0x57, 0x2e,
0x6a, 0xd5, 0x37, 0x30, 0x88, 0x02, 0xa5, 0xb5, 0xa8, 0x5d, 0xff, 0x80, 0xcd, 0xc8, 0x9d, 0x29,
0xf5, 0xdb, 0x87, 0x63, 0xf2, 0xdc, 0x9d, 0x7b, 0x38, 0x9c, 0xf3, 0xbb, 0x70, 0x1c, 0x4a, 0x4b,
0xc6, 0xc6, 0x03, 0x6b, 0xab, 0x11, 0x5a, 0xea, 0x7b, 0x3d, 0x6a, 0xee, 0xbf, 0xc2, 0x04, 0x2e,
0x3f, 0x0d, 0xf1, 0xab, 0xaa, 0x35, 0x22, 0x5c, 0xa8, 0xe2, 0x9b, 0xa4, 0x17, 0x78, 0xd1, 0x55,
0xea, 0x34, 0xde, 0xc0, 0xc1, 0xd0, 0x24, 0xcf, 0x9d, 0xb5, 0x48, 0x7c, 0x00, 0x7f, 0xa4, 0xae,
0x69, 0xad, 0x3c, 0x04, 0x5e, 0x24, 0xd2, 0xff, 0x2b, 0xfc, 0x80, 0x63, 0xfd, 0xa3, 0xaa, 0x94,
0xcc, 0xa0, 0x95, 0x21, 0xbc, 0x05, 0xc1, 0xb9, 0x29, 0xe6, 0xad, 0x8e, 0xb3, 0x62, 0xc6, 0x7b,
0xf0, 0x39, 0x77, 0x23, 0x6b, 0xa3, 0xe0, 0xf7, 0x65, 0x65, 0xcd, 0xd2, 0xe4, 0x2a, 0x5d, 0x96,
0xa6, 0xa7, 0x04, 0xae, 0x17, 0xb4, 0x8c, 0xf8, 0xb7, 0xab, 0x08, 0x5f, 0x40, 0xbc, 0xe9, 0xa6,
0x53, 0x78, 0x17, 0x9f, 0xf8, 0xe3, 0x0d, 0xfe, 0x51, 0xee, 0xdd, 0x3d, 0x48, 0x78, 0x56, 0xfa,
0xee, 0xef, 0xe7, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x29, 0x64, 0x7d, 0x56, 0x07, 0x01, 0x00,
0x00,
}
用命令安装:go get google.golang.org/grpc
另外在安装插件:
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
package main
import (
pb "grpc-hello/helloworld"
"log"
"os"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
const (
address = "127.0.0.1:8082"
)
func main() {
log.SetOutput(os.Stdout)
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewUserServiceClient(conn)
userInfo := &pb.UserInfo{
Name: "Tome111111", //proto.String("XCL-gRPC"),
Sex: "man",
Weight: 16,
}
r, err := c.Login(context.Background(), userInfo)
if err != nil {
log.Fatalf("登录失败! %v", err)
}
log.Println(r.RSay, r.RName)
}
package main
import (
pb "grpc-hello/helloworld"
"log"
"net"
"os"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
const (
port = "127.0.0.1:8082"
)
type server struct{}
func (s *server) Login(ctx context.Context, usr *pb.UserInfo) (*pb.FuncResponse, error) {
log.Println("Server...... Login() UserInfo:", usr)
return &pb.FuncResponse{RSay: "hello", RName: usr.Name}, nil
}
func main() {
log.SetOutput(os.Stdout)
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterUserServiceServer(s, &server{})
log.Println("Server......")
s.Serve(lis)
}
运行的结果: