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

作者:怀素真 时间:2024-05-29 22:06:05 

rpc 包提供了一个方法来通过网络或者其他的I/O连接进入对象的外部方法. 一个server注册一个对象, 标记它成为可见对象类型名字的服务。注册后,对象的外部方法就可以远程调用了。一个server可以注册多个 不同类型的对象,但是却不可以注册多个相同类型的对象。

只有满足这些标准的方法才会被远程调用视为可见;其他的方法都会被忽略:

- 方法是外部可见的。
- 方法有两个参数,参数的类型都是外部可见的。
- 方法的第二个参数是一个指针。
- 方法有返回类型错误

一、基于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);

}

来源:https://www.cnblogs.com/jkko123/p/7039675.html

标签:go,rpc,调用
0
投稿

猜你喜欢

  • 怎么使用pipenv管理你的python项目

    2021-01-29 06:58:41
  • 合理关闭XHTML标签

    2008-06-25 13:20:00
  • Python简单实现图片转字符画的实例项目

    2023-02-24 02:01:47
  • Python 调用 zabbix api的方法示例

    2021-07-15 02:35:09
  • 如何利用python 读取配置文件

    2023-11-08 14:40:21
  • 轻设计,让网站灵敏轻便的6个技巧

    2009-12-07 21:26:00
  • 如何基于python实现不邻接植花

    2023-10-14 16:35:45
  • 在pycharm中创建django项目的示例代码

    2023-04-07 17:39:25
  • Python笔试面试题小结

    2022-07-17 12:51:23
  • 3个asp简单技巧

    2009-11-26 20:55:00
  • 树莓派安装OpenCV3完整过程的实现

    2023-11-06 06:26:08
  • 用ASP木马实现FTP和解压缩

    2008-02-13 08:47:00
  • Python如何实现FTP功能

    2021-10-22 15:08:25
  • python解析html提取数据,并生成word文档实例解析

    2023-10-19 13:50:38
  • python中matplotlib实现随鼠标滑动自动标注代码

    2023-09-02 10:49:47
  • SQL Substring提取部分字符串

    2024-01-14 20:03:07
  • 网页设计中的层次感

    2007-11-05 18:19:00
  • Python高级特性切片(Slice)操作详解

    2022-04-07 20:28:02
  • asp将数据库中的信息存储至XML文件中

    2007-09-19 12:54:00
  • SQL Server 2012使用Offset/Fetch Next实现分页数据查询

    2024-01-25 03:54:55
  • asp之家 网络编程 m.aspxhome.com