《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)
}