rpc
rpc简介
rpc入门
从字面上可以看出,remote远程那么就一定离不开网络
应用:比如北京的客户端去调用上海服务器的方法
在开始rpc之前,先回顾一下网络socket通信
server端:
net.Listen() ===>listener 创建监听器
listener.Accept() ===> conn 启动监听 建立连接
conn.Read()
conn.Write()
defer conn.Close() / listener.Close()
client端:
net.Dial() ===>conn
conn.Write()
conn.Read()
defer conn.Close()
rpc的使用步骤:
- 服务端:
- 注册rpc服务对象:给对象绑定方法(1,定义类 2,绑定类方法)
rpc.RegisterName("服务名",回调对象) //下面的HelloWorld就是回调函数
- 创建监听器
listener,err := net.Listen()
- 建立连接
conn, err := listener.Accept()
- 将连接绑定rpc服务
rpc.ServeConn(conn)
- 客户端:
- 用rpc去连接服务器
conn, err := rpc.Dial()
- 像调用本地函数一样去调用远程函数
conn.Call("服务名.方法名", 传入参数, 传出参数)
rpc相关函数:
- 注册rpc服务
func RegisterName(name string, rcvr interface{}) error
1. 参数1-name 服务名,string.
2. 参数2-rcvr 对应的rpc对象 空接口类型/指针 该对象绑定的方法需满足:
a,必须是导出的(包外可见,首字母大写)
b,方法必须有2个参数,第一个参数是传入参数
第二个是传出参数都是导出类型或内置类型
c,方法的第二个参数必须是指针(传出参数)
d,方法只有一个error接口类型的返回值
请看下面的示例:
type World struct{}
//方法只有一个error接口类型的返回值,eg
func (this *World) HelloWorld(name string, resp *string) error{
}
rpc.RegisterName("服务名",new(World))
- 绑定rpc服务
func ServeConn(conn io.ReadWriteCloser)
conn: 就是成功建立连接的socket --- conn
- 调用远程函数
func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error
serviceMethod: "服务名.方法名"
args: 传入参数,方法所需要的数据
reply:传出参数,定义var 变量, &变量名 完成传参
rpc-server
package main
import (
"log"
"net"
"net/rpc"
)
//定义类对象
type World struct {
}
//绑定类方法
func (this *World) HelloWorld(name string, resp *string) error { //HelloWorld首字母要大写
*resp = name + "你好!"
return nil
}
func main() {
//1,注册rpc服务 绑定对象方法
err := rpc.RegisterName("hello", new(World))
if err != nil {
log.Println("注册rpc服务失败:", err)
return
}
//2,设置监听
listener, err := net.Listen("tcp", "127.0.0.1:8800")
if err != nil {
log.Println("net.Listen() error:", err)
return
}
defer listener.Close()
log.Printf("开始监听")
//3,建立连接
conn, err := listener.Accept()
if err != nil {
log.Println("listener.Accept() error:", err)
return
}
log.Printf("连接成功")
//4,绑定服务
rpc.ServeConn(conn)
}
rpc-client
package main
import (
"fmt"
"log"
"net/rpc"
)
func main() {
//1. 用rpc去连接服务器
conn, err := rpc.Dial("tcp", "127.0.0.1:8800")
if err != nil {
log.Println("rpc.Dial() error:", err)
return
}
defer conn.Close()
//2,调用远程服务
var reply string //接收返回值(传出参数)
err = conn.Call("hello.HelloWorld", "Scott", &reply)
if err != nil {
log.Println("conn.Call() error:", err)
return
}
fmt.Println(reply)
}
run: