grpc 示例

1

go get -u github.com/golang/protobuf/proto

go get -u github.com/golang/protobuf/protoc-gen-go

2 下载

https://github.com/google/protobuf/releases
将bin目录添加到path目录下。

3 编写proto文件rpctest.proto

// 使用方法:protoc -I ./rpctest/ ./rpctest/rpctest.proto --go_out=plugins=grpc:rpctest
syntax = "proto3";
package serverpb;

service funcname
{
    rpc FuncName(MessReq) returns (MessRes);
};

message MessReq{
    int32 NameId = 1 [ json_name="nameid" ];
};

message MessRes{
    int32 result = 1;
};

//
执行方法:protoc -I ./rpctest/ ./rpctest/rpctest.proto –go_out=plugins=grpc:rpctest

路径根据自己的路径来处理

4 生成go文件。

就会获取到

// Code generated by protoc-gen-go. DO NOT EDIT.
// source: funname.proto

package serverpb

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

type MessReq struct {
    NameId int32 `protobuf:"varint,1,opt,name=NameId,json=nameid" json:"NameId,omitempty"`
}

func (m *MessReq) Reset()                    { *m = MessReq{} }
func (m *MessReq) String() string            { return proto.CompactTextString(m) }
func (*MessReq) ProtoMessage()               {}
func (*MessReq) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0} }

func (m *MessReq) GetNameId() int32 {
    if m != nil {
        return m.NameId
    }
    return 0
}

type MessRes struct {
    Result int32 `protobuf:"varint,1,opt,name=result" json:"result,omitempty"`
}

func (m *MessRes) Reset()                    { *m = MessRes{} }
func (m *MessRes) String() string            { return proto.CompactTextString(m) }
func (*MessRes) ProtoMessage()               {}
func (*MessRes) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{1} }

func (m *MessRes) GetResult() int32 {
    if m != nil {
        return m.Result
    }
    return 0
}

func init() {
    proto.RegisterType((*MessReq)(nil), "serverpb.MessReq")
    proto.RegisterType((*MessRes)(nil), "serverpb.MessRes")
}

// 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 Funcname service

type FuncnameClient interface {
    FuncName(ctx context.Context, in *MessReq, opts ...grpc.CallOption) (*MessRes, error)
}

type funcnameClient struct {
    cc *grpc.ClientConn
}

func NewFuncnameClient(cc *grpc.ClientConn) FuncnameClient {
    return &funcnameClient{cc}
}

func (c *funcnameClient) FuncName(ctx context.Context, in *MessReq, opts ...grpc.CallOption) (*MessRes, error) {
    out := new(MessRes)
    err := grpc.Invoke(ctx, "/serverpb.funcname/FuncName", in, out, c.cc, opts...)
    if err != nil {
        return nil, err
    }
    return out, nil
}

// Server API for Funcname service

type FuncnameServer interface {
    FuncName(context.Context, *MessReq) (*MessRes, error)
}

func RegisterFuncnameServer(s *grpc.Server, srv FuncnameServer) {
    s.RegisterService(&_Funcname_serviceDesc, srv)
}

func _Funcname_FuncName_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
    in := new(MessReq)
    if err := dec(in); err != nil {
        return nil, err
    }
    if interceptor == nil {
        return srv.(FuncnameServer).FuncName(ctx, in)
    }
    info := &grpc.UnaryServerInfo{
        Server:     srv,
        FullMethod: "/serverpb.funcname/FuncName",
    }
    handler := func(ctx context.Context, req interface{}) (interface{}, error) {
        return srv.(FuncnameServer).FuncName(ctx, req.(*MessReq))
    }
    return interceptor(ctx, in, info, handler)
}

var _Funcname_serviceDesc = grpc.ServiceDesc{
    ServiceName: "serverpb.funcname",
    HandlerType: (*FuncnameServer)(nil),
    Methods: []grpc.MethodDesc{
        {
            MethodName: "FuncName",
            Handler:    _Funcname_FuncName_Handler,
        },
    },
    Streams:  []grpc.StreamDesc{},
    Metadata: "funname.proto",
}

func init() { proto.RegisterFile("funname.proto", fileDescriptor3) }

var fileDescriptor3 = []byte{
    // 134 bytes of a gzipped FileDescriptorProto
    0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4d, 0x2b, 0xcd, 0xcb,
    0x4b, 0xcc, 0x4d, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x28, 0x4e, 0x2d, 0x2a, 0x4b,
    0x2d, 0x2a, 0x48, 0x52, 0x52, 0xe4, 0x62, 0xf7, 0x4d, 0x2d, 0x2e, 0x0e, 0x4a, 0x2d, 0x14, 0x12,
    0xe3, 0x62, 0xf3, 0x4b, 0xcc, 0x4d, 0xf5, 0x4c, 0x91, 0x60, 0x54, 0x60, 0xd4, 0x60, 0x0d, 0x62,
    0x03, 0x69, 0xc8, 0x4c, 0x41, 0x28, 0x29, 0x06, 0x29, 0x29, 0x4a, 0x2d, 0x2e, 0xcd, 0x29, 0x81,
    0x29, 0x81, 0xf0, 0x8c, 0x6c, 0xb8, 0x38, 0xd2, 0x4a, 0xf3, 0x92, 0x41, 0x1a, 0x84, 0x0c, 0xb8,
    0x38, 0xdc, 0x4a, 0xf3, 0x92, 0x41, 0x46, 0x09, 0x09, 0xea, 0xc1, 0x2c, 0xd2, 0x83, 0xda, 0x22,
    0x85, 0x21, 0x54, 0x9c, 0xc4, 0x06, 0x76, 0x94, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xdf, 0x35,
    0x1b, 0xe8, 0xa5, 0x00, 0x00, 0x00,
}

5 编写服务端代码

根据.go文件编写服务端代码

package main

import (
    "context"
    "fmt"
    "net"
    proto "rpctest"

    "google.golang.org/grpc"
)

type server struct {
}

func (s *server) FuncName(c context.Context, in *proto.MessReq) (*proto.MessRes, error) {
    return &proto.MessRes{Result :in.NameId }, nil
}

func main() {
    listen, err := net.Listen("tcp", ":50051")
    if err != nil {
        fmt.Println("listen failed err:", err)
        return
    }
    s := grpc.NewServer()
    proto.RegisterGreeterServer(s, &server{})
    s.Serve(listen)
}

6 编写客户端代码

package main

import (
    "context"
    "log"
    proto "rpctest"
    "google.golang.org/grpc"
)

func main() {
    conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
    if err != nil {
        log.Fatal("new dial failed err:", err)
    }

    defer conn.Close()
    c := proto.NewGreeterClient(conn)
    r, err := c.FuncName(context.Background(), &proto.MessReq{NameId : 1})
    if err != nil {
        log.Fatal("get reply failed err:", err)
    }
    log.Print(r.GetMessage())
}

其他服务方法:

(1) 单项 RPC,即客户端发送一个请求给服务端,从服务端获取一个应答,就像一次普通的函数调用。

rpc SayHello(HelloRequest) returns (HelloResponse){
}

(2) 服务端流式 RPC,即客户端发送一个请求给服务端,可获取一个数据流用来读取一系列消息。客户端从返回的数据流里一直读取直到没有更多消息为止。

rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){
}

(3)客户端流式 RPC,即客户端用提供的一个数据流写入并发送一系列消息给服务端。一旦客户端完成消息写入,就等待服务端读取这些消息并返回应答。

rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {
}

(4) 双向流式 RPC,即两边都可以分别通过一个读写数据流来发送一系列消息。这两个数据流操作是相互独立的,所以客户端和服务端能按其希望的任意顺序读写,例如:服务端可以在写应答前等待所有的客户端消息,或者它可以先读一个消息再写一个消息,或者是读写相结合的其他方式。每个数据流里消息的顺序会被保持。

rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){
}

连接

猜你喜欢

转载自blog.csdn.net/suiban7403/article/details/80071100