golang——net/rpc包學習

一、rpc包

rpc包提供了經過網絡或其餘I/O鏈接對一個對象的導出方法的訪問。網絡

只有知足以下標準的方法才能用於遠程訪問,其他方法會被忽略:異步

(1)方法是導出的
(2)方法有兩個參數,都是導出類型或內建類型
(3)方法的第二個參數是指針
(4)方法只有一個error接口類型的返回值tcp

func (t *T) MethodName(argType T1, replyType *T2) erroride

其中T、T1和T2都能被encoding/gob包序列化。函數

方法的第一個參數表明調用者提供的參數;第二個參數表明返回給調用者的參數。spa

方法的返回值,若是非nil,將被做爲字符串回傳,在客戶端看來就和errors.New建立的同樣。線程

若是返回了錯誤,回覆的參數將不會被髮送給客戶端。debug

代碼示例:指針

package main

import (
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/rpc"
)

// Args 參數
type Args struct {
	A, B int
}

// Quotient 商、餘數
type Quotient struct {
	Quo, Rem int
}

// Arith 算術服務
type Arith int

// Multiply 乘法服務
func (*Arith) Multiply(args *Args, reply *int) error {
	*reply = args.A * args.B
	return nil
}

// Divide 除法服務
func (*Arith) Divide(args *Args, quo *Quotient) error {
	if args.B == 0 {
		return errors.New("除數不能爲零")
	}
	quo.Quo = args.A / args.B
	quo.Rem = args.A % args.B
	return nil
}

// 錯誤檢查
func checkErr(err error) {
	if err != nil {
		log.Fatalln(err)
	}
}

func main() {
	//開啓服務
	arith := new(Arith)
	//使用默認服務對象
	err := rpc.Register(arith)
	checkErr(err)
	//默認路徑
	// const (
	// 	DefaultRPCPath   = "/_goRPC_"
	// 	DefaultDebugPath = "/debug/rpc"
	// )
	rpc.HandleHTTP()
	//設置監聽
	lis, err := net.Listen("tcp", ":1234")
	checkErr(err)
	go http.Serve(lis, nil)

	//客戶端請求服務
	client, err := rpc.DialHTTP("tcp", ":1234")
	checkErr(err)
	defer client.Close()
	//乘法
	args := &Args{A: 17, B: 3}
	var reply int
	err = client.Call("Arith.Multiply", args, &reply)
	checkErr(err)
	fmt.Printf("Arith.Multiply:%d * %d = %d\n", args.A, args.B, reply)
	//除法
	quotient := new(Quotient)
	call := client.Go("Arith.Divide", args, quotient, nil)
	<-call.Done
	fmt.Printf("Arith.Divide:%d / %d = %d .... %d\n", args.A, args.B, quotient.Quo, quotient.Rem)
}

//輸出
//Arith.Multiply:17 * 3 = 51
// Arith.Divide:17 / 3 = 5 .... 2

二、客戶端

2.一、type Client struct{}日誌

Client類型表明RPC客戶端。

同一個客戶端可能有多個未返回的調用,也可能被多個go程同時使用。

2.二、經常使用方法

(1)func NewClient(conn io.ReadWriteCloser) *Client

NewClient返回一個新的Client,以管理對鏈接另外一端的服務的請求。

(2)func Dial(network, address string) (*Client, error)

Dial在指定的網絡和地址與RPC服務端鏈接。

(3)func DialHTTP(network, address string) (*Client, error)

DialHTTP在指定的網絡和地址與在默認HTTP RPC路徑監聽的HTTP RPC服務端鏈接。

(4)func DialHTTPPath(network, address, path string) (*Client, error)

DialHTTPPath在指定的網絡、地址和路徑與HTTP RPC服務端鏈接。

(5)func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error

Call調用指定的方法,等待調用返回,將結果寫入reply,而後返回執行的錯誤狀態。

(6)func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call

Go異步的調用函數。本方法Call結構體類型指針的返回值表明該次遠程調用。

通道類型的參數done會在本次調用完成時發出信號(經過返回本次Go方法的返回值)。

若是done爲nil,Go會申請一個新的通道(寫入返回值的Done字段);若是done非nil,done必須有緩衝,不然Go方法會故意崩潰。

(7)func (client *Client) Close() error

關閉客戶端。

三、服務端

3.一、type Server struct{}

rpc包提供默認的服務對象,可直接經過「rpc.」進行使用。

3.二、經常使用方法

(1)func NewServer() *Server

建立並返回一個*Server。

(2)func (server *Server) Register(rcvr interface{}) error

註冊服務。

若是rcvr不是一個導出類型的值,或者該類型沒有知足要求的方法,Register會返回錯誤。

Register也會使用log包將錯誤寫入日誌。

客戶端可使用格式爲"Type.Method"的字符串訪問這些方法,其中Type是rcvr的具體類型。

(3)func (server *Server) RegisterName(name string, rcvr interface{}) error

RegisterName相似Register,但使用提供的name代替rcvr的具體類型名做爲服務名。

(4)func (server *Server) Accept(lis net.Listener)

Accept接收監聽器l獲取的鏈接,而後服務每個鏈接。

Accept會阻塞,調用者應另開線程。

(5)func (server *Server) ServeHTTP(w http.ResponseWriter, req *http.Request)

ServeHTTP實現了迴應RPC請求的http.Handler接口。

(6)func (server *Server) HandleHTTP(rpcPath, debugPath string)

HandleHTTP註冊server的RPC信息HTTP處理器對應到rpcPath,註冊server的debug信息HTTP處理器對應到debugPath。

HandleHTTP會註冊到http.DefaultServeMux。以後,仍須要調用http.Serve(),通常會另開線程:"go http.Serve(l, nil)"

相關文章
相關標籤/搜索