在本例中,使用通道代替socket实现RPC过程,客户端和服务器运行在同一个进程,服务器和客户端在两个goroute中。
应用知识:goroute,select,RPC过程
1、客户端请求和接收封装
下面的代码封装了向服务器请求数据,等待服务器返回数据,如果请求方超时,利用select,该函数还会处理超时逻辑。如下:
1
2
3
4
5
6
7
8
9
|
func RPCClient(ch chan string, req string) (string, error) {
ch <- req
select {
case ack := <-ch:
return ack, nil
case <-time.After(time.Second):
return "", errors.New("Time out")
}
}
|
2、服务器接收和反馈数据
服务器接收到客户端的任意数据后,先打印再通过通道返回给客户端一个固定的字符串(hello),表示服务器已经收到请求。
1
2
3
4
5
6
7
8
9
|
func RPCServer(ch chan string) {
for {
data := <-ch
fmt.Println("server received:", data)
//time.Sleep(time.Second * 2)
ch <- "roger"
}
}
|
注:为了模拟服务端相应超时,可以用time.Sleep()函数让goroute执行暂停2秒,这样会触发客户端“Time out”
3、主流程
主流程中会创建一个无缓冲的字符串格式通道。将通道传给服务器的RPCServer()函数,这个函数会并发执行,使用RPCClient函数通过ch对服务器发出RPC请求同时接收服务器反馈数据或者等待超时。
1
2
3
4
5
6
7
8
9
10
11
12
|
func main() {
ch := make(chan string)
go RPCServer(ch)
recv, err := RPCClient(ch, "hi")
if err != nil {
fmt.Println(err)
} else {
fmt.Println("client received", recv)
}
}
|
4、输出结果如下:
1
2
|
server received: hi
client received helllo
|