设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间13 现在时间13 缓存数据 希望你一辈子都是小孩儿 对所有事都好奇 爱哼小曲 永远快乐 喜欢和讨厌不用遮掩 每天都能跟喜欢的人讲一大堆废话 也能互道晚安❤️

希望你一辈子都是小孩儿 对所有事都好奇 爱哼小曲 永远快乐 喜欢和讨厌不用遮掩 每天都能跟喜欢的人讲一大堆废话 也能互道晚安❤️ -- 晚安

查看: 2483|回复: 5

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

[复制链接]

  离线 

TA的专栏

  • 打卡等级:热心大叔
  • 打卡总天数:236
  • 打卡月天数:0
  • 打卡总奖励:4272
  • 最近打卡:2025-03-29 13:17:14
等级头衔

等級:晓枫资讯-上等兵

在线时间
6 小时

积分成就
威望
0
贡献
438
主题
414
精华
0
金钱
5650
积分
932
注册时间
2023-1-6
最后登录
2025-3-29

发表于 2023-3-7 22:04:10 | 显示全部楼层 |阅读模式
rpc 包提供了一个方法来通过网络或者其他的I/O连接进入对象的外部方法. 一个server注册一个对象, 标记它成为可见对象类型名字的服务。注册后,对象的外部方法就可以远程调用了。一个server可以注册多个 不同类型的对象,但是却不可以注册多个相同类型的对象。
只有满足这些标准的方法才会被远程调用视为可见;其他的方法都会被忽略:
- 方法是外部可见的。
- 方法有两个参数,参数的类型都是外部可见的。
- 方法的第二个参数是一个指针。
- 方法有返回类型错误

一、基于http的RPC
服务端:
  1. package main;



  2. import (

  3.   "net/rpc"

  4.   "net/http"

  5.   "log"

  6. )



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

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



  9. //注意字段必须是导出

  10. type Params struct {

  11.   Width, Height int;

  12. }



  13. type Rect struct{}



  14. //函数必须是导出的

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

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

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

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

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

  20.   *ret = p.Width * p.Height;

  21.   return nil;

  22. }



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

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

  25.   return nil;

  26. }



  27. func main() {

  28.   rect := new(Rect);

  29.   //注册一个rect服务

  30.   rpc.Register(rect);

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

  32.   rpc.HandleHTTP();

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

  34.   if err != nil {

  35.     log.Fatal(err);

  36.   }

  37. }
复制代码
客户端:
  1. package main;



  2. import (

  3.   "net/rpc"

  4.   "log"

  5.   "fmt"

  6. )



  7. type Params struct {

  8.   Width, Height int;

  9. }



  10. func main() {

  11.   //连接远程rpc服务

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

  13.   if err != nil {

  14.     log.Fatal(err);

  15.   }

  16.   ret := 0;

  17.   //调用远程方法

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

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

  20.   if err2 != nil {

  21.     log.Fatal(err2);

  22.   }

  23.   fmt.Println(ret);

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

  25.   if err3 != nil {

  26.     log.Fatal(err3);

  27.   }

  28.   fmt.Println(ret);

  29. }
复制代码
二、基于tcp的RPC
服务端:
  1. package main;



  2. import (

  3.   "net"

  4.   "log"

  5.   "net/rpc"

  6. )



  7. //注意字段必须是导出

  8. type Params struct {

  9.   Width, Height int;

  10. }



  11. type Rect struct{}



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

  13.   *ret = p.Width * p.Height;

  14.   return nil;

  15. }



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

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

  18.   return nil;

  19. }



  20. func chkError(err error) {

  21.   if err != nil {

  22.     log.Fatal(err);

  23.   }

  24. }



  25. func main() {

  26.   rect := new(Rect);

  27.   //注册rpc服务

  28.   rpc.Register(rect);

  29.   //获取tcpaddr

  30.   tcpaddr, err := net.ResolveTCPAddr("tcp4", "127.0.0.1:8080");

  31.   chkError(err);

  32.   //监听端口

  33.   tcplisten, err2 := net.ListenTCP("tcp", tcpaddr);

  34.   chkError(err2);

  35.   //死循环处理连接请求

  36.   for {

  37.     conn, err3 := tcplisten.Accept();

  38.     if err3 != nil {

  39.       continue;

  40.     }

  41.     //使用goroutine单独处理rpc连接请求

  42.     go rpc.ServeConn(conn);

  43.   }

  44. }
复制代码
客户端:
  1. package main;



  2. import (

  3.   "net/rpc"

  4.   "fmt"

  5.   "log"

  6. )



  7. type Params struct {

  8.   Width, Height int;

  9. }



  10. func main() {

  11.   //连接远程rpc服务

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

  13.   rpc, err := rpc.Dial("tcp", "127.0.0.1:8080");

  14.   if err != nil {

  15.     log.Fatal(err);

  16.   }

  17.   ret := 0;

  18.   //调用远程方法

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

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

  21.   if err2 != nil {

  22.     log.Fatal(err2);

  23.   }

  24.   fmt.Println(ret);

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

  26.   if err3 != nil {

  27.     log.Fatal(err3);

  28.   }

  29.   fmt.Println(ret);

  30. }
复制代码
三、JSON RPC 方式
jsonrpc方式是数据编码采用了json,而不是gob编码。
服务端:
  1. package main;



  2. import (

  3.   "net"

  4.   "log"

  5.   "net/rpc"

  6.   "net/rpc/jsonrpc"

  7. )



  8. //注意字段必须是导出

  9. type Params struct {

  10.   Width, Height int;

  11. }



  12. type Rect struct{}



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

  14.   *ret = p.Width * p.Height;

  15.   return nil;

  16. }



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

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

  19.   return nil;

  20. }



  21. func chkError(err error) {

  22.   if err != nil {

  23.     log.Fatal(err);

  24.   }

  25. }



  26. func main() {

  27.   rect := new(Rect);

  28.   //注册rpc服务

  29.   rpc.Register(rect);

  30.   //获取tcpaddr

  31.   tcpaddr, err := net.ResolveTCPAddr("tcp4", "127.0.0.1:8080");

  32.   chkError(err);

  33.   //监听端口

  34.   tcplisten, err2 := net.ListenTCP("tcp", tcpaddr);

  35.   chkError(err2);

  36.   for {

  37.     conn, err3 := tcplisten.Accept();

  38.     if err3 != nil {

  39.       continue;

  40.     }

  41.     //使用goroutine单独处理rpc连接请求

  42.     //这里使用jsonrpc进行处理

  43.     go jsonrpc.ServeConn(conn);

  44.   }

  45. }
复制代码
客户端:
  1. package main;



  2. import (

  3.   "fmt"

  4.   "log"

  5.   "net/rpc/jsonrpc"

  6. )



  7. type Params struct {

  8.   Width, Height int;

  9. }



  10. func main() {

  11.   //连接远程rpc服务

  12.   //这里使用jsonrpc.Dial

  13.   rpc, err := jsonrpc.Dial("tcp", "127.0.0.1:8080");

  14.   if err != nil {

  15.     log.Fatal(err);

  16.   }

  17.   ret := 0;

  18.   //调用远程方法

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

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

  21.   if err2 != nil {

  22.     log.Fatal(err2);

  23.   }

  24.   fmt.Println(ret);

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

  26.   if err3 != nil {

  27.     log.Fatal(err3);

  28.   }

  29.   fmt.Println(ret);

  30. }
复制代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持晓枫资讯。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

  • 打卡等级:即来则安
  • 打卡总天数:21
  • 打卡月天数:0
  • 打卡总奖励:228
  • 最近打卡:2025-04-17 05:30:38
等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
264
积分
44
注册时间
2023-3-5
最后登录
2025-4-17

发表于 2023-5-18 01:31:27 | 显示全部楼层
免费分享的大佬,反手就是一个赞~~~~
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
12
积分
16
注册时间
2023-4-25
最后登录
2023-4-25

发表于 2023-7-2 00:12:52 | 显示全部楼层
看看,学习学习~~~~
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
20
积分
20
注册时间
2022-12-26
最后登录
2022-12-26

发表于 2023-11-26 08:51:57 | 显示全部楼层
感谢楼主,顶。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
19
积分
18
注册时间
2022-12-25
最后登录
2022-12-25

发表于 2024-10-15 23:32:15 | 显示全部楼层
顶顶更健康!!!
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
11
积分
2
注册时间
2024-11-3
最后登录
2024-11-3

发表于 2025-2-18 01:47:04 | 显示全部楼层
感谢楼主分享。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼
3楼
4楼
5楼
6楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表