go语言学习-RPC的简单使用

什么是RPC?

  • RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

  • RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。

1.GO语言中HTTPRPC调用:

RPC server:

package main

import (
    "github.com/pkg/errors"
    "net/rpc"
    "net/http"
    "fmt"
)

type Main int

type Args struct {
    A int
    B int
}

func (m *Main)Multiply(arg Args,reply *int) error{
    *reply = arg.A * arg.B
    fmt.Println("Multiply 被远程调用")
    return nil
}

type Quotion struct {
    Quo , Rem int
}

func (m *Main)Division(arg Args,quo *Quotion) error{
    if arg.B == 0{
        return errors.New("devide by zero")
    }

    quo.Quo = arg.A / arg.B
    quo.Rem = arg.A % arg.B
    fmt.Println("Division 被远程调用")
    return  nil
}

func main() {

    main := new(Main)

    rpc.Register(main)
    rpc.HandleHTTP()

    err := http.ListenAndServe(":1234",nil)
    if err != nil{
        fmt.Println(err.Error())
    }

}

RPC Client

package  main

import (
    "flag"
    //"net/http"
    "net/rpc"
    "fmt"
    "runtime"
)

type Args struct {
    A,B int
}

type Quotion struct {
    Quo,Rem int
}

func main(){
    var host string
    flag.StringVar(&host,"host","127.0.0.1","目标主机")
    flag.Parse()

    client,err:= rpc.DialHTTP("tcp",host+":1234")
    if err != nil{
        _, file, line, _ :=runtime.Caller(0)
        fmt.Println(err.Error(),file,line)
        return
    }

    arg := &Args{5,5}
    var reply int
    err =client.Call("Main.Multiply",arg,&reply)
    if err != nil{
        _, file, line, _ :=runtime.Caller(0)
        fmt.Println(err.Error(),file,line)
        return
    }
    fmt.Printf("Multiply: %dx%d=%d\n",arg.A,arg.B,reply)

    var que Quotion
    err = client.Call("Main.Division",arg,&que)
    if err != nil{
        _, file, line, _ :=runtime.Caller(0)
        fmt.Println(err.Error(),file,line)
        return
    }
    fmt.Printf("Main.Division %d/%d=%d,%d%%%d=%d\n",arg.A,arg.B,que.Quo,arg.A,arg.B,que.Rem)
}
  • 先启动服务端,再启动客户端,下面是输出结果:
//客户端输出结果:
Multiply: 5x5=25
Main.Division 5/5=1,5%5=0

服务端输出结果:
Multiply 被远程调用
Division 被远程调用

GO语言中TCPRPC调用:

RPC server:

tcprpc的server和httprpc的server相差不多,使用httprpc时rpc有直接调用即可,在tcp中rpc得自己先创建一个tcp服务端,创建之后将每次连接的conn传给传入rpc.ServeConn(conn)即可

package main

import (
    "github.com/pkg/errors"
    "net/rpc"
    "fmt"
    "net"
)

type Main int

type Args struct {
    A int
    B int
}

func (m *Main)Multiply(arg Args,reply *int) error{
    *reply = arg.A * arg.B
    fmt.Println("Multiply 被远程调用")
    return nil
}

type Quotion struct {
    Quo , Rem int
}

func (m *Main)Division(arg Args,quo *Quotion) error{
    if arg.B == 0{
        return errors.New("devide by zero")
    }

    quo.Quo = arg.A / arg.B
    quo.Rem = arg.A % arg.B
    fmt.Println("Division 被远程调用")
    return  nil
}

func main(){
    main := new(Main)

    rpc.Register(main)

    tcpAddr ,err:= net.ResolveTCPAddr("tcp",":1234")
    if err != nil{
        fmt.Println(err)
        return
    }

    listen,err := net.ListenTCP("tcp",tcpAddr)
    if err != nil{
        fmt.Println(err)
        return
    }

    for{
        conn,err := listen.Accept()
        if err !=nil{
            fmt.Println(err)
            continue
        }
        //只需要将连接句柄传入rpc包会自动解析
        rpc.ServeConn(conn)
    }
}
RPC 客户端和HTTPRPC客户端基本一样只需将下面代码修改即可

RPC Client

//将创建客户端从DialHTTP改为Dial即可
client,err:= rpc.Dial("tcp",host+":1234")

输出结果和上面一样

GO语言中JSONRPC调用:

RPC server:

//只需要代码中引入"net/rpc/jsonrpc"包,把下面这行代码修改即可
jsonrpc.ServeConn(conn)

RPC client:

//只需要代码中引入"net/rpc/jsonrpc"包,把下面这行代码修改即可
client,err:= jsonrpc.Dial("tcp",host+":1234")

猜你喜欢

转载自blog.csdn.net/len_yue_mo_fu/article/details/81119302