# package rpc
`import "net/rpc"`
rpc包提供了通过网络或其他I/O连接对一个对象的导出方法的访问。服务端注册一个对象,使它作为一个服务被暴露,服务的名字是该对象的类型名。注册之后,对象的导出方法就可以被远程访问。服务端可以注册多个不同类型的对象(服务),但注册具有相同类型的多个对象是错误的。
只有满足如下标准的方法才能用于远程访问,其余方法会被忽略:
```
- 方法是导出的
- 方法有两个参数,都是导出类型或内建类型
- 方法的第二个参数是指针
- 方法只有一个error接口类型的返回值
```
事实上,方法必须看起来像这样:
```
func (t *T) MethodName(argType T1, replyType *T2) error
```
其中T、T1和T2都能被encoding/gob包序列化。这些限制即使使用不同的编解码器也适用。(未来,对定制的编解码器可能会使用较宽松一点的限制)
方法的第一个参数代表调用者提供的参数;第二个参数代表返回给调用者的参数。方法的返回值,如果非nil,将被作为字符串回传,在客户端看来就和errors.New创建的一样。如果返回了错误,回复的参数将不会被发送给客户端。
服务端可能会单个连接上调用ServeConn管理请求。更典型地,它会创建一个网络监听器然后调用Accept;或者,对于HTTP监听器,调用HandleHTTP和http.Serve。
想要使用服务的客户端会创建一个连接,然后用该连接调用NewClient。
更方便的函数Dial(DialHTTP)会在一个原始的连接(或HTTP连接)上依次执行这两个步骤。
生成的Client类型值有两个方法,Call和Go,它们的参数为要调用的服务和方法、一个包含参数的指针、一个用于接收接个的指针。
Call方法会等待远端调用完成,而Go方法异步的发送调用请求并使用返回的Call结构体类型的Done通道字段传递完成信号。
除非设置了显式的编解码器,本包默认使用[encoding/gob](http://godoc.org/encoding/gob)包来传输数据。
这是一个简单的例子。一个服务端想要导出Arith类型的一个对象:
```
package server
type Args struct {
A, B int
}
type Quotient struct {
Quo, Rem int
}
type Arith int
func (t *Arith) Multiply(args *Args, reply *int) error {
*reply = args.A * args.B
return nil
}
func (t *Arith) Divide(args *Args, quo *Quotient) error {
if args.B == 0 {
return errors.New("divide by zero")
}
quo.Quo = args.A / args.B
quo.Rem = args.A % args.B
return nil
}
```
服务端会调用(用于HTTP服务):
```
arith := new(Arith)
rpc.Register(arith)
rpc.HandleHTTP()
l, e := net.Listen("tcp", ":1234")
if e != nil {
log.Fatal("listen error:", e)
}
go http.Serve(l, nil)
```
此时,客户端可看到服务"Arith"及它的方法"Arith.Multiply"、"Arith.Divide"。要调用方法,客户端首先呼叫服务端:
```
client, err := rpc.DialHTTP("tcp", serverAddress + ":1234")
if err != nil {
log.Fatal("dialing:", err)
}
```
然后,客户端可以执行远程调用:
```
// Synchronous call
args := &server.Args{7,8}
var reply int
err = client.Call("Arith.Multiply", args, &reply)
if err != nil {
log.Fatal("arith error:", err)
}
fmt.Printf("Arith: %d*%d=%d", args.A, args.B, reply)
```
或:
```
// Asynchronous call
quotient := new(Quotient)
divCall := client.Go("Arith.Divide", args, quotient, nil)
replyCall := <-divCall.Done // will be equal to divCall
// check errors, print, etc.
```
服务端的实现应为客户端提供简单、类型安全的包装。
## Index
* [Constants](#pkg-constants)
* [Variables](#pkg-variables)
* [type ServerError](#ServerError)
* [func (e ServerError) Error() string](#ServerError.Error)
* [type Request](#Request)
* [type Response](#Response)
* [type ClientCodec](#ClientCodec)
* [type ServerCodec](#ServerCodec)
* [type Call](#Call)
* [type Client](#Client)
* [func NewClient(conn io.ReadWriteCloser) \*Client](#NewClient)
* [func NewClientWithCodec(codec ClientCodec) \*Client](#NewClientWithCodec)
* [func Dial(network, address string) (\*Client, error)](#Dial)
* [func DialHTTP(network, address string) (\*Client, error)](#DialHTTP)
* [func DialHTTPPath(network, address, path string) (\*Client, error)](#DialHTTPPath)
* [func (client \*Client) Call(serviceMethod string, args interface{}, reply interface{}) error](#Client.Call)
* [func (client \*Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan \*Call) \*Call](#Client.Go)
* [func (client \*Client) Close() error](#Client.Close)
* [type Server](#Server)
* [func NewServer() \*Server](#NewServer)
* [func (server \*Server) Register(rcvr interface{}) error](#Server.Register)
* [func (server \*Server) RegisterName(name string, rcvr interface{}) error](#Server.RegisterName)
* [func (server \*Server) Accept(lis net.Listener)](#Server.Accept)
* [func (server \*Server) ServeConn(conn io.ReadWriteCloser)](#Server.ServeConn)
* [func (server \*Server) ServeCodec(codec ServerCodec)](#Server.ServeCodec)
* [func (server \*Server) ServeRequest(codec ServerCodec) error](#Server.ServeRequest)
* [func (server \*Server) ServeHTTP(w http.ResponseWriter, req \*http.Request)](#Server.ServeHTTP)
* [func (server \*Server) HandleHTTP(rpcPath, debugPath string)](#Server.HandleHTTP)
* [func Register(rcvr interface{}) error](#Register)
* [func RegisterName(name string, rcvr interface{}) error](#RegisterName)
* [func Accept(lis net.Listener)](#Accept)
* [func ServeConn(conn io.ReadWriteCloser)](#ServeConn)
* [func ServeCodec(codec ServerCodec)](#ServeCodec)
* [func ServeRequest(codec ServerCodec) error](#ServeRequest)
* [func HandleHTTP()](#HandleHTTP)
## Constants
```
const (
// HandleHTTP使用的默认值
DefaultRPCPath = "/_goRPC_"
DefaultDebugPath = "/debug/rpc"
)
```
## Variables
```
var DefaultServer = NewServer()
```
DefaultServer是\*Server的默认实例,本包和Server方法同名的函数都是对其方法的封装。
```
var ErrShutdown = errors.New("connection is shut down")
```
## type [ServerError](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L20 "View Source")
```
type ServerError string
```
ServerError represents an error that has been returned from the remote side of the RPC connection.
### func (ServerError) [Error](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L22 "View Source")
```
func (e ServerError) Error() string
```
## type [Request](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L167 "View Source")
```
type Request struct {
ServiceMethod string // 格式:"Service.Method"
Seq uint64 // 由客户端选择的序列号
// 内含隐藏或非导出字段
}
```
Request是每个RPC调用请求的头域。它是被内部使用的,这里的文档用于帮助debug,如分析网络拥堵时。
## type [Response](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L176 "View Source")
```
type Response struct {
ServiceMethod string // 对应请求的同一字段
Seq uint64 // 对应请求的同一字段
Error string // 可能的错误
// 内含隐藏或非导出字段
}
```
Response是每个RPC调用回复的头域。它是被内部使用的,这里的文档用于帮助debug,如分析网络拥堵时。
## type [ClientCodec](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L62 "View Source")
```
type ClientCodec interface {
// 本方法必须能安全的被多个go程同时使用
WriteRequest(*Request, interface{}) error
ReadResponseHeader(*Response) error
ReadResponseBody(interface{}) error
Close() error
}
```
ClientCodec接口实现了RPC会话的客户端一侧RPC请求的写入和RPC回复的读取。客户端调用WriteRequest来写入请求到连接,然后成对调用ReadRsponseHeader和ReadResponseBody以读取回复。客户端在结束该连接的事务时调用Close方法。ReadResponseBody可以使用nil参数调用,以强制回复的主体被读取然后丢弃。
## type [ServerCodec](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L618 "View Source")
```
type ServerCodec interface {
ReadRequestHeader(*Request) error
ReadRequestBody(interface{}) error
// 本方法必须能安全的被多个go程同时使用
WriteResponse(*Response, interface{}) error
Close() error
}
```
ServerCodec接口实现了RPC会话的服务端一侧RPC请求的读取和RPC回复的写入。服务端通过成对调用方法ReadRequestHeader和ReadRequestBody从连接读取请求,然后调用WriteResponse来写入回复。服务端在结束该连接的事务时调用Close方法。ReadRequestBody可以使用nil参数调用,以强制请求的主体被读取然后丢弃。
## type [Call](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L29 "View Source")
```
type Call struct {
ServiceMethod string // 调用的服务和方法的名称
Args interface{} // 函数的参数(下层为结构体指针)
Reply interface{} // 函数的回复(下层为结构体指针)
Error error // 在调用结束后,保管错误的状态
Done chan *Call // 对其的接收操作会阻塞,直到远程调用结束
}
```
Call类型代表一个执行中/执行完毕的RPC会话。
## type [Client](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L41 "View Source")
```
type Client struct {
// 内含隐藏或非导出字段
}
```
Client类型代表RPC客户端。同一个客户端可能有多个未返回的调用,也可能被多个go程同时使用。
### func [NewClient](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L188 "View Source")
```
func NewClient(conn io.ReadWriteCloser) *Client
```
NewClient返回一个新的Client,以管理对连接另一端的服务的请求。它添加缓冲到连接的写入侧,以便将回复的头域和有效负载作为一个单元发送。
### func [NewClientWithCodec](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L196 "View Source")
```
func NewClientWithCodec(codec ClientCodec) *Client
```
NewClientWithCodec类似NewClient,但使用指定的编解码器,以编码请求主体和解码回复主体。
### func [Dial](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L269 "View Source")
```
func Dial(network, address string) (*Client, error)
```
Dial在指定的网络和地址与RPC服务端连接。
### func [DialHTTP](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L236 "View Source")
```
func DialHTTP(network, address string) (*Client, error)
```
DialHTTP在指定的网络和地址与在默认HTTP RPC路径监听的HTTP RPC服务端连接。
### func [DialHTTPPath](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L242 "View Source")
```
func DialHTTPPath(network, address, path string) (*Client, error)
```
DialHTTPPath在指定的网络、地址和路径与HTTP RPC服务端连接。
### func (\*Client) [Call](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L314 "View Source")
```
func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error
```
Call调用指定的方法,等待调用返回,将结果写入reply,然后返回执行的错误状态。
### func (\*Client) [Go](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L292 "View Source")
```
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方法会故意崩溃。
### func (\*Client) [Close](https://github.com/golang/go/blob/master/src/net/rpc/client.go#L277 "View Source")
```
func (client *Client) Close() error
```
## type [Server](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L184 "View Source")
```
type Server struct {
// 内含隐藏或非导出字段
}
```
Server代表RPC服务端。
### func [NewServer](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L194 "View Source")
```
func NewServer() *Server
```
NewServer创建并返回一个\*Server。
### func (\*Server) [Register](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L227 "View Source")
```
func (server *Server) Register(rcvr interface{}) error
```
Register在server注册并公布rcvr的方法集中满足如下要求的方法:
```
- 方法是导出的
- 方法有两个参数,都是导出类型或内建类型
- 方法的第二个参数是指针
- 方法只有一个error接口类型的返回值
```
如果rcvr不是一个导出类型的值,或者该类型没有满足要求的方法,Register会返回错误。Register也会使用[log](http://godoc.org/log)包将错误写入日志。客户端可以使用格式为"Type.Method"的字符串访问这些方法,其中Type是rcvr的具体类型。
### func (\*Server) [RegisterName](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L233 "View Source")
```
func (server *Server) RegisterName(name string, rcvr interface{}) error
```
RegisterName类似Register,但使用提供的name代替rcvr的具体类型名作为服务名。
### func (\*Server) [Accept](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L592 "View Source")
```
func (server *Server) Accept(lis net.Listener)
```
Accept接收监听器l获取的连接,然后服务每一个连接。Accept会阻塞,调用者应另开线程:"go server.Accept(l)"
### func (\*Server) [ServeConn](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L427 "View Source")
```
func (server *Server) ServeConn(conn io.ReadWriteCloser)
```
ServeConn在单个连接上执行server。ServeConn会阻塞,服务该连接直到客户端挂起。调用者一般应另开线程调用本函数:"go server.ServeConn(conn)"。ServeConn在该连接使用gob(参见encoding/gob包)有线格式。要使用其他的编解码器,可调用ServeCodec方法。
### func (\*Server) [ServeCodec](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L435 "View Source")
```
func (server *Server) ServeCodec(codec ServerCodec)
```
ServeCodec类似ServeConn,但使用指定的编解码器,以编码请求主体和解码回复主体。
### func (\*Server) [ServeRequest](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L460 "View Source")
```
func (server *Server) ServeRequest(codec ServerCodec) error
```
ServeRequest类似ServeCodec,但异步的服务单个请求。它不会在调用结束后关闭codec。
### func (\*Server) [ServeHTTP](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L657 "View Source")
```
func (server *Server) ServeHTTP(w http.ResponseWriter, req *http.Request)
```
ServeHTTP实现了回应RPC请求的http.Handler接口。
### func (\*Server) [HandleHTTP](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L676 "View Source")
```
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)"
## func [Register](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L603 "View Source")
```
func Register(rcvr interface{}) error
```
Register在DefaultServer注册并公布rcvr的方法。
## func [RegisterName](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L607 "View Source")
```
func RegisterName(name string, rcvr interface{}) error
```
RegisterName函数类似Register函数,但使用提供的name代替rcvr的具体类型名作为服务名。
## func [Accept](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L651 "View Source")
```
func Accept(lis net.Listener)
```
Accept接收监听器l获取的连接,然后将每一个连接交给DefaultServer服务。Accept会阻塞,调用者应另开线程:"go server.Accept(l)"
## func [ServeConn](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L632 "View Source")
```
func ServeConn(conn io.ReadWriteCloser)
```
ServeConn在单个连接上执行DefaultServer。ServeConn会阻塞,服务该连接直到客户端挂起。调用者一般应另开线程调用本函数:"go ServeConn(conn)"。ServeConn在该连接使用gob(参见encoding/gob包)有线格式。要使用其他的编解码器,可调用ServeCodec方法。
## func [ServeCodec](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L638 "View Source")
```
func ServeCodec(codec ServerCodec)
```
ServeCodec类似ServeConn,但使用指定的编解码器,以编码请求主体和解码回复主体。
## func [ServeRequest](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L644 "View Source")
```
func ServeRequest(codec ServerCodec) error
```
ServeRequest类似ServeCodec,但异步的服务单个请求。它不会在调用结束后关闭codec。
## func [HandleHTTP](https://github.com/golang/go/blob/master/src/net/rpc/server.go#L684 "View Source")
```
func HandleHTTP()
```
HandleHTTP函数注册DefaultServer的RPC信息HTTP处理器对应到DefaultRPCPath,和DefaultServer的debug处理器对应到DefaultDebugPath。HandleHTTP函数会注册到http.DefaultServeMux。之后,仍需要调用http.Serve(),一般会另开线程:"go http.Serve(l, nil)"
- 库
- package achive
- package tar
- package zip
- package bufio
- package builtin
- package bytes
- package compress
- package bzip2
- package flate
- package gzip
- package lzw
- package zlib
- package container
- package heap
- package list
- package ring
- package crypto
- package aes
- package cipher
- package des
- package dsa
- package ecdsa
- package elliptic
- package hmac
- package md5
- package rand
- package rc4
- package rsa
- package sha1
- package sha256
- package sha512
- package subtle
- package tls
- package x509
- package pkix
- package database
- package sql
- package driver
- package encoding
- package ascii85
- package asn1
- package base32
- package base64
- package binary
- package csv
- package gob
- package hex
- package json
- package pem
- package xml
- package errors
- package expvar
- package flag
- package fmt
- package go
- package doc
- package format
- package parser
- package printer
- package hash
- package adler32
- package crc32
- package crc64
- package fnv
- package html
- package template
- package image
- package color
- package palette
- package draw
- package gif
- package jpeg
- package png
- package index
- package suffixarray
- package io
- package ioutil
- package log
- package syslog
- package math
- package big
- package cmplx
- package rand
- package mime
- package multipart
- package net
- package http
- package cgi
- package cookiejar
- package fcgi
- package httptest
- package httputil
- package pprof
- package mail
- package rpc
- package jsonrpc
- package smtp
- package textproto
- package url
- package os
- package exec
- package signal
- package user
- package path
- package filepath
- package reflect
- package regexp
- package runtime
- package cgo
- package debug
- package pprof
- package race
- package sort
- package strconv
- package strings
- package sync
- package atomic
- package text
- package scanner
- package tabwriter
- package template
- package time
- package unicode
- package utf16
- package utf8
- package unsafe