《GO语言高级编程》设计中案例,仅作为笔记进行收藏。基于上下⽂可以针对不同客户端提供定制化的RPC服务,同时可以方便地为RPC服务增加简单的登陆状态的验证。
1.server/main.go
package main
import (
"fmt"
"log"
"net"
"net/rpc"
)
type HelloService struct {
// 增加了对应链接的conn成员
conn net.Conn
isLogin bool
}
func ServeHelloService(conn net.Conn) {
p := rpc.NewServer()
p.Register(&HelloService{conn: conn})
p.ServeConn(conn)
}
func (p *HelloService) Login(request string, reply *string) error {
if request != "user:password" {
log.Println("login failed")
return fmt.Errorf("auth failed")
}
log.Println("login ok")
p.isLogin = true
return nil
}
func (p *HelloService) Hello(request string, reply *string) error {
if !p.isLogin {
return fmt.Errorf("please login")
}
// 可以根据conn成员识别不同链接的RPC调用
*reply = "hello:" + request + ", from " + p.conn.RemoteAddr().String()
return nil
}
func main() {
listener, err := net.Listen("tcp", ":1234")
if err != nil {
log.Fatal("ListenTCP error:", err)
}
for {
conn, err := listener.Accept()
if err != nil {
log.Fatal("Accept error:", err)
}
go ServeHelloService(conn)
}
}
2.client/main.go
package main
import (
"fmt"
"log"
"net/rpc"
)
func main(){
client,err:=rpc.Dial("tcp","localhost:1234")
if err!=nil{
log.Fatal("dialing:",err)
}
var reply string
err=client.Call("HelloService.Login","abc",&reply)
if err!=nil{
log.Println(err)
}else{
log.Println("login ok")
}
err=client.Call("HelloService.Login","user:password",&reply)
if err!=nil{
log.Println(err)
}else{
log.Println("login ok")
}
err = client.Call("HelloService.Hello", "hello,world", &reply)
if err != nil {
log.Fatal(err)
}
fmt.Println(reply)
}