一、基于http的RPC
服务端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | 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); } } |
客户端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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
服务端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | 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); } } |
客户端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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编码。
服务端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 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); } } |
客户端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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); } |
版权声明:博主文章,可以不经博主允许随意转载,随意修改,知识是用来传播的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决