首页 > 文章列表 > Go语言net包RPC远程调用三种方式http与json-rpc及tcp

Go语言net包RPC远程调用三种方式http与json-rpc及tcp

golang
487 2022-12-17

rpc有多种调用方式,http、json-rpc、tcp

一、服务端

在代码中,启动了三个服务


package main

import (

	"log"

	"net"

	"net/http"

	"net/rpc"

	"net/rpc/jsonrpc"

	"sync"

) 

//go对RPC的支持,支持三个级别:TCP、HTTP、JSONRPC

//go的RPC只支持GO开发的服务器与客户端之间的交互,因为采用了gob编码 

//注意字段必须是导出

type Params struct {

	Width, Height int

} 

type Rect struct{} 

//函数必须是导出的

//必须有两个导出类型参数

//第一个参数是接收参数

//第二个参数是返回给客户端参数,必须是指针类型

//函数还要有一个返回值error

func (r *Rect) Area(p Params, ret *int) error {

	*ret = p.Width * p.Height

	return nil

} 

func (r *Rect) Perimeter(p Params, ret *int) error {

	*ret = (p.Width + p.Height) * 2

	return nil

} 

func main() {

	rect := new(Rect)

	//注册一个rect服务

	rpc.Register(rect)

	var wg sync.WaitGroup

	wg.Add(3)

	go func() {

		//把服务处理绑定到http协议上

		rpc.HandleHTTP()

		err := http.ListenAndServe(":8080", nil)

		wg.Wait()

		if err != nil {

			log.Fatal(err)

			defer wg.Done()

		}

	}()

	log.Println("http rpc service start success addr:8080") 

	go func() {

 

		tcpaddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:8081")

		tcplisten, err := net.ListenTCP("tcp", tcpaddr)

		if err != nil {

			log.Fatal(err)

			defer wg.Done()

		}

		for {

			conn, err3 := tcplisten.Accept()

			if err3 != nil {

				continue

			}

			go rpc.ServeConn(conn)  

		} 

	}()

	log.Println("tcp rpc service start success addr:8081")

 	go func() { 

		tcpaddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:8082")

		tcplisten, err := net.ListenTCP("tcp", tcpaddr)

		if err != nil {

			log.Fatal(err)

			defer wg.Done()

		}

		for {

			conn, err3 := tcplisten.Accept()

			if err3 != nil {

				continue

			}

			go jsonrpc.ServeConn(conn)

		} 

	}()

	log.Println("tcp json-rpc service start success addr:8082") 

	wg.Wait()

}

二、http客户端


package main

import (

	"net/rpc"

	"log"

	"fmt"

)

type Params struct {

	Width, Height int

}

func main() {

	//连接远程rpc服务

	rpc, err := rpc.DialHTTP("tcp", "127.0.0.1:8080")

	if err != nil {

		log.Fatal(err)

	}

	ret := 0;

	//调用远程方法

	//注意第三个参数是指针类型

	err2 := rpc.Call("Rect.Area", Params{50, 100}, &ret)

	if err2 != nil {

		log.Fatal(err2)

	}

	fmt.Println(ret)

	err3 := rpc.Call("Rect.Perimeter", Params{50, 100}, &ret)

	if err3 != nil {

		log.Fatal(err3)

	}

	fmt.Println(ret)

}

三、TCP客户端


package main 

import (

	"net/rpc"

	"fmt"

	"log"

) 

type Params struct {

	Width, Height int

} 

func main() {

	//连接远程rpc服务

	//这里使用Dial,http方式使用DialHTTP,其他代码都一样

	rpc, err := rpc.Dial("tcp", "127.0.0.1:8081")

	if err != nil {

		log.Fatal(err)

	}

	ret := 0

	//调用远程方法

	//注意第三个参数是指针类型

	err2 := rpc.Call("Rect.Area", Params{50, 100}, &ret)

	if err2 != nil {

		log.Fatal(err2)

	}

	fmt.Println(ret)

	err3 := rpc.Call("Rect.Perimeter", Params{50, 100}, &ret)

	if err3 != nil {

		log.Fatal(err3)

	}

	fmt.Println(ret)

}

四、json客户端


package main 

import ( 

	"fmt"

	"log"

	"net/rpc/jsonrpc"

) 

type Params struct {

	Width, Height int

} 

func main() {

	//连接远程rpc服务

	rpc, err := jsonrpc.Dial("tcp", "127.0.0.1:8082")

	if err != nil {

		log.Fatal(err)

	}

	ret := 0

	//调用远程方法

	//注意第三个参数是指针类型

	err2 := rpc.Call("Rect.Area", Params{150, 100}, &ret)

	if err2 != nil {

		log.Fatal(err2)

	}

	fmt.Println(ret)

	err3 := rpc.Call("Rect.Perimeter", Params{150, 100}, &ret)

	if err3 != nil {

		log.Fatal(err3)

	}

	fmt.Println(ret)

}

五、运行结果