• go语言net包rpc远程调用的使用


    一、基于http的RPC

    服务端:

    package main;
    
    import (
    	"net/rpc"
    	"net/http"
    	"log"
    )
    
    //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);
    	//把服务处理绑定到http协议上
    	rpc.HandleHTTP();
    	err := http.ListenAndServe(":8080", nil);
    	if err != nil {
    		log.Fatal(err);
    	}
    }

    客户端:

    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的RPC

    服务端:

    package main;
    
    import (
    	"net"
    	"log"
    	"net/rpc"
    )
    
    //注意字段必须是导出
    type Params struct {
    	Width, Height int;
    }
    
    type Rect struct{}
    
    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 chkError(err error) {
    	if err != nil {
    		log.Fatal(err);
    	}
    }
    
    func main() {
    	rect := new(Rect);
    	//注册rpc服务
    	rpc.Register(rect);
    	//获取tcpaddr
    	tcpaddr, err := net.ResolveTCPAddr("tcp4", "127.0.0.1:8080");
    	chkError(err);
    	//监听端口
    	tcplisten, err2 := net.ListenTCP("tcp", tcpaddr);
    	chkError(err2);
    	//死循环处理连接请求
    	for {
    		conn, err3 := tcplisten.Accept();
    		if err3 != nil {
    			continue;
    		}
    		//使用goroutine单独处理rpc连接请求
    		go rpc.ServeConn(conn);
    	}
    }
    

    客户端:

    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: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);
    }
    

    三、JSON RPC 方式

    jsonrpc方式是数据编码采用了json,而不是gob编码。

    服务端:

    package main;
    
    import (
    	"net"
    	"log"
    	"net/rpc"
    	"net/rpc/jsonrpc"
    )
    
    //注意字段必须是导出
    type Params struct {
    	Width, Height int;
    }
    
    type Rect struct{}
    
    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 chkError(err error) {
    	if err != nil {
    		log.Fatal(err);
    	}
    }
    
    func main() {
    	rect := new(Rect);
    	//注册rpc服务
    	rpc.Register(rect);
    	//获取tcpaddr
    	tcpaddr, err := net.ResolveTCPAddr("tcp4", "127.0.0.1:8080");
    	chkError(err);
    	//监听端口
    	tcplisten, err2 := net.ListenTCP("tcp", tcpaddr);
    	chkError(err2);
    	for {
    		conn, err3 := tcplisten.Accept();
    		if err3 != nil {
    			continue;
    		}
    		//使用goroutine单独处理rpc连接请求
    		//这里使用jsonrpc进行处理
    		go jsonrpc.ServeConn(conn);
    	}
    }
    

    客户端:

    package main;
    
    import (
    	"fmt"
    	"log"
    	"net/rpc/jsonrpc"
    )
    
    type Params struct {
    	Width, Height int;
    }
    
    func main() {
    	//连接远程rpc服务
    	//这里使用jsonrpc.Dial
    	rpc, err := jsonrpc.Dial("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);
    }
    

  • 相关阅读:
    洛谷 P2986 [USACO10MAR]伟大的奶牛聚集Great Cow Gat…(树规)
    STREAMING #5 题解 3.高位网络
    冲刺NOIP2015提高组复赛模拟试题(五) 3.破坏基地
    冲刺NOIP2015提高组复赛模拟试题(五)2.道路修建
    冲刺NOIP2015提高组复赛模拟试题(五)1.数学作业
    洛谷P1186 玛丽卡 spfa+删边
    清北学堂 day6 花
    清北学堂 day6 兔子
    C++ STL 全排列函数
    flash分区的意义
  • 原文地址:https://www.cnblogs.com/jkko123/p/7039675.html
Copyright © 2020-2023  润新知