go-doc-rpc

net/rpc库

服务器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package main

import (
"errors"
"fmt"
"log"
"net"
"net/http"
"net/rpc"
"os"
)

// 算数运算结构体
type Arith struct {
}

// 算数运算请求结构体
type ArithRequest struct {
A int
B int
}

// 算数运算响应结构体
type ArithResponse struct {
Pro int // 乘积
Quo int // 商
Rem int // 余数
}

// 乘法运算方法
func (this *Arith) Multiply(req ArithRequest, res *ArithResponse) error {
res.Pro = req.A * req.B
return nil
}

// 除法运算方法
func (this *Arith) Divide(req ArithRequest, res *ArithResponse) error {
if req.B == 0 {
return errors.New("divide by zero")
}
res.Quo = req.A / req.B
res.Rem = req.A % req.B
return nil
}

func main() {
rpc.Register(new(Arith)) // 注册rpc服务
rpc.HandleHTTP() // 采用http协议作为rpc载体

lis, err := net.Listen("tcp", "127.0.0.1:8095")
if err != nil {
log.Fatalln("fatal error: ", err)
}

fmt.Fprintf(os.Stdout, "%s", "start connection")

http.Serve(lis, nil)
}
客户端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package main

import (
"fmt"
"log"
"net/rpc"
)

// 算数运算请求结构体
type ArithRequest struct {
A int
B int
}

// 算数运算响应结构体
type ArithResponse struct {
Pro int // 乘积
Quo int // 商
Rem int // 余数
}

func main() {
conn, err := rpc.DialHTTP("tcp", "127.0.0.1:8095")
if err != nil {
log.Fatalln("dailing error: ", err)
}

req := ArithRequest{9, 2}
var res ArithResponse

err = conn.Call("Arith.Multiply", req, &res) // 乘法运算
if err != nil {
log.Fatalln("arith error: ", err)
}
fmt.Printf("%d * %d = %d\n", req.A, req.B, res.Pro)

err = conn.Call("Arith.Divide", req, &res)
if err != nil {
log.Fatalln("arith error: ", err)
}
fmt.Printf("%d / %d, quo is %d, rem is %d\n", req.A, req.B, res.Quo, res.Rem)
}

net/rpc/jsonrpc库

服务器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package main

import (
"errors"
"fmt"
"log"
"net"
"net/rpc"
"net/rpc/jsonrpc"
"os"
)

// 算数运算结构体
type Arith struct {
}

// 算数运算请求结构体
type ArithRequest struct {
A int
B int
}

// 算数运算响应结构体
type ArithResponse struct {
Pro int // 乘积
Quo int // 商
Rem int // 余数
}

// 乘法运算方法
func (this *Arith) Multiply(req ArithRequest, res *ArithResponse) error {
res.Pro = req.A * req.B
return nil
}

// 除法运算方法
func (this *Arith) Divide(req ArithRequest, res *ArithResponse) error {
if req.B == 0 {
return errors.New("divide by zero")
}
res.Quo = req.A / req.B
res.Rem = req.A % req.B
return nil
}

func main() {
rpc.Register(new(Arith)) // 注册rpc服务

lis, err := net.Listen("tcp", "127.0.0.1:8096")
if err != nil {
log.Fatalln("fatal error: ", err)
}

fmt.Fprintf(os.Stdout, "%s", "start connection")

for {
conn, err := lis.Accept() // 接收客户端连接请求
if err != nil {
continue
}

go func(conn net.Conn) { // 并发处理客户端请求
fmt.Fprintf(os.Stdout, "%s", "new client in coming\n")
jsonrpc.ServeConn(conn)
}(conn)
}
}
客户端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package main

import (
"fmt"
"log"
"net/rpc/jsonrpc"
)

// 算数运算请求结构体
type ArithRequest struct {
A int
B int
}

// 算数运算响应结构体
type ArithResponse struct {
Pro int // 乘积
Quo int // 商
Rem int // 余数
}

func main() {
conn, err := jsonrpc.Dial("tcp", "127.0.0.1:8096")
if err != nil {
log.Fatalln("dailing error: ", err)
}

req := ArithRequest{9, 2}
var res ArithResponse

err = conn.Call("Arith.Multiply", req, &res) // 乘法运算
if err != nil {
log.Fatalln("arith error: ", err)
}
fmt.Printf("%d * %d = %d\n", req.A, req.B, res.Pro)

err = conn.Call("Arith.Divide", req, &res)
if err != nil {
log.Fatalln("arith error: ", err)
}
fmt.Printf("%d / %d, quo is %d, rem is %d\n", req.A, req.B, res.Quo, res.Rem)
}

protorpc库

准备

需要先安装protobuf和proto工具

1
2
3
4
go install code.google.com/p/goprotobuf/proto
go install code.google.com/p/goprotobuf/protoc-gen-go
go get -u golang.org/x/text
go get -u google.golang.org/grpc

github-grpc地址
github-protobuf地址
github-text地址
github-genproto地址
grpc api

文件

proto文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
syntax = "proto3"; //指定proto版本

package proto;

//定义请求结构
message HelloRequest{
string name=1;
}

//定义响应结构
message HelloReply{
string message=1;
}

//定义Hello服务
service Hello{
//定义服务中的方法
rpc SayHello(HelloRequest)returns (HelloReply){}
}

使用 protoc -I . --go_out=plugins=grpc:. ./hello.proto 命令生成 go 文件

服务器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package main

import (
"fmt"
"net"
pb "test/frame/tRpc/pro"

"golang.org/x/net/context"
"google.golang.org/grpc"
)

const (
//gRPC服务地址
Address = "127.0.0.1:5002"
)

//定义一个helloServer并实现约定的接口
type helloService struct{}

func (h helloService) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
resp := new(pb.HelloReply)
resp.Message = "hello" + in.Name + "."
return resp, nil
}

var HelloServer = helloService{}

func main() {
listen, err := net.Listen("tcp", Address)
if err != nil {
fmt.Printf("failed to listen:%v", err)
}
fmt.Println("Listen on0" + Address)
//实现gRPC Server0
s := grpc.NewServer()
//注册helloServer为客户端提供服务
fmt.Println("Listen on1" + Address)
pb.RegisterHelloServer(s, HelloServer) //内部调用了s.RegisterServer()
fmt.Println("Listen on2" + Address)

s.Serve(listen)

}
客户端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package main

import (
"fmt"
pb "test/frame/tRpc/pro"

"golang.org/x/net/context"
"google.golang.org/grpc"
)

const (
Address = "127.0.0.1:5002"
)

func main() {
//连接gRPC服务器
conn, err := grpc.Dial(Address, grpc.WithInsecure())
if err != nil {
fmt.Println(err)
}
defer conn.Close()

//初始化客户端
c := pb.NewHelloClient(conn)

//调用方法
reqBody := new(pb.HelloRequest)
reqBody.Name = "gRPC"
r, err := c.SayHello(context.Background(), reqBody)
if err != nil {
fmt.Println(err)
}
fmt.Println(r.Message)

}