1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
6 The rpc package provides access to the exported methods of an object across a
7 network or other I/O connection. A server registers an object, making it visible
8 as a service with the name of the type of the object. After registration, exported
9 methods of the object will be accessible remotely. A server may register multiple
10 objects (services) of different types but it is an error to register multiple
11 objects of the same type.
13 Only methods that satisfy these criteria will be made available for remote access;
14 other methods will be ignored:
16 - the method receiver and name are exported, that is, begin with an upper case letter.
17 - the method has two arguments, both pointers to exported types.
18 - the method has return type os.Error.
20 The method's first argument represents the arguments provided by the caller; the
21 second argument represents the result parameters to be returned to the caller.
22 The method's return value, if non-nil, is passed back as a string that the client
23 sees as an os.ErrorString.
25 The server may handle requests on a single connection by calling ServeConn. More
26 typically it will create a network listener and call Accept or, for an HTTP
27 listener, HandleHTTP and http.Serve.
29 A client wishing to use the service establishes a connection and then invokes
30 NewClient on the connection. The convenience function Dial (DialHTTP) performs
31 both steps for a raw network connection (an HTTP connection). The resulting
32 Client object has two methods, Call and Go, that specify the service and method to
33 call, a pointer containing the arguments, and a pointer to receive the result
36 Call waits for the remote call to complete; Go launches the call asynchronously
37 and returns a channel that will signal completion.
39 Package "gob" is used to transport the data.
41 Here is a simple example. A server wishes to export an object of type Arith:
49 type Quotient struct {
55 func (t *Arith) Multiply(args *Args, reply *int) os.Error {
56 *reply = args.A * args.B
60 func (t *Arith) Divide(args *Args, quo *Quotient) os.Error {
62 return os.ErrorString("divide by zero")
64 quo.Quo = args.A / args.B
65 quo.Rem = args.A % args.B
69 The server calls (for HTTP service):
74 l, e := net.Listen("tcp", ":1234")
76 log.Exit("listen error:", e)
80 At this point, clients can see a service "Arith" with methods "Arith.Multiply" and
81 "Arith.Divide". To invoke one, a client first dials the server:
83 client, err := rpc.DialHTTP("tcp", serverAddress + ":1234")
85 log.Exit("dialing:", err)
88 Then it can make a remote call:
91 args := &server.Args{7,8}
93 err = client.Call("Arith.Multiply", args, &reply)
95 log.Exit("arith error:", err)
97 fmt.Printf("Arith: %d*%d=%d", args.A, args.B, *reply)
102 quotient := new(Quotient)
103 divCall := client.Go("Arith.Divide", args, "ient, nil)
104 replyCall := <-divCall.Done // will be equal to divCall
105 // check errors, print, etc.
107 A server implementation will often provide a simple, type-safe wrapper for the
127 // Defaults used by HandleHTTP
128 DefaultRPCPath
= "/_goRPC_"
129 DefaultDebugPath
= "/debug/rpc"
132 // Precompute the reflect type for os.Error. Can't use os.Error directly
133 // because Typeof takes an empty interface value. This is annoying.
134 var unusedError
*os
.Error
135 var typeOfOsError
= reflect
.Typeof(unusedError
).(*reflect
.PtrType
).Elem()
137 type methodType
struct {
138 sync
.Mutex
// protects counters
139 method reflect
.Method
140 argType
*reflect
.PtrType
141 replyType
*reflect
.PtrType
145 type service
struct {
146 name
string // name of service
147 rcvr reflect
.Value
// receiver of methods for the service
148 typ reflect
.Type
// type of the receiver
149 method
map[string]*methodType
// registered methods
152 // Request is a header written before every RPC call. It is used internally
153 // but documented here as an aid to debugging, such as when analyzing
155 type Request
struct {
156 ServiceMethod
string // format: "Service.Method"
157 Seq
uint64 // sequence number chosen by client
160 // Response is a header written before every RPC return. It is used internally
161 // but documented here as an aid to debugging, such as when analyzing
163 type Response
struct {
164 ServiceMethod
string // echoes that of the Request
165 Seq
uint64 // echoes that of the request
166 Error
string // error, if any.
169 // ClientInfo records information about an RPC client connection.
170 type ClientInfo
struct {
175 // Server represents an RPC Server.
177 sync
.Mutex
// protects the serviceMap
178 serviceMap
map[string]*service
181 // NewServer returns a new Server.
182 func NewServer() *Server
{
183 return &Server
{serviceMap
: make(map[string]*service
)}
186 // DefaultServer is the default instance of *Server.
187 var DefaultServer
= NewServer()
189 // Is this an exported - upper case - name?
190 func isExported(name
string) bool {
191 rune
, _
:= utf8
.DecodeRuneInString(name
)
192 return unicode
.IsUpper(rune
)
195 // Register publishes in the server the set of methods of the
196 // receiver value that satisfy the following conditions:
198 // - two arguments, both pointers to exported structs
199 // - one return value, of type os.Error
200 // It returns an error if the receiver is not an exported type or has no
202 func (server
*Server
) Register(rcvr
interface{}) os
.Error
{
204 defer server
.Unlock()
205 if server
.serviceMap
== nil {
206 server
.serviceMap
= make(map[string]*service
)
209 s
.typ
= reflect
.Typeof(rcvr
)
210 s
.rcvr
= reflect
.NewValue(rcvr
)
211 sname
:= reflect
.Indirect(s
.rcvr
).Type().Name()
213 log
.Exit("rpc: no service name for type", s
.typ
.String())
215 if s
.typ
.PkgPath() != "" && !isExported(sname
) {
216 s
:= "rpc Register: type " + sname
+ " is not exported"
218 return os
.ErrorString(s
)
220 if _
, present
:= server
.serviceMap
[sname
]; present
{
221 return os
.ErrorString("rpc: service already defined: " + sname
)
224 s
.method
= make(map[string]*methodType
)
226 // Install the methods
227 for m
:= 0; m
< s
.typ
.NumMethod(); m
++ {
228 method
:= s
.typ
.Method(m
)
231 if mtype
.PkgPath() != "" ||
!isExported(mname
) {
234 // Method needs three ins: receiver, *args, *reply.
235 if mtype
.NumIn() != 3 {
236 log
.Println("method", mname
, "has wrong number of ins:", mtype
.NumIn())
239 argType
, ok
:= mtype
.In(1).(*reflect
.PtrType
)
241 log
.Println(mname
, "arg type not a pointer:", mtype
.In(1))
244 replyType
, ok
:= mtype
.In(2).(*reflect
.PtrType
)
246 log
.Println(mname
, "reply type not a pointer:", mtype
.In(2))
249 if argType
.Elem().PkgPath() != "" && !isExported(argType
.Elem().Name()) {
250 log
.Println(mname
, "argument type not exported:", argType
)
253 if replyType
.Elem().PkgPath() != "" && !isExported(replyType
.Elem().Name()) {
254 log
.Println(mname
, "reply type not exported:", replyType
)
257 if mtype
.NumIn() == 4 {
259 if t
!= reflect
.Typeof((*ClientInfo
)(nil)) {
260 log
.Println(mname
, "last argument not *ClientInfo")
264 // Method needs one out: os.Error.
265 if mtype
.NumOut() != 1 {
266 log
.Println("method", mname
, "has wrong number of outs:", mtype
.NumOut())
269 if returnType
:= mtype
.Out(0); returnType
!= typeOfOsError
{
270 log
.Println("method", mname
, "returns", returnType
.String(), "not os.Error")
273 s
.method
[mname
] = &methodType
{method
: method
, argType
: argType
, replyType
: replyType
}
276 if len(s
.method
) == 0 {
277 s
:= "rpc Register: type " + sname
+ " has no exported methods of suitable type"
279 return os
.ErrorString(s
)
281 server
.serviceMap
[s
.name
] = s
285 // A value sent as a placeholder for the response when the server receives an invalid request.
286 type InvalidRequest
struct {
290 var invalidRequest
= InvalidRequest
{1}
292 func _new(t
*reflect
.PtrType
) *reflect
.PtrValue
{
293 v
:= reflect
.MakeZero(t
).(*reflect
.PtrValue
)
294 v
.PointTo(reflect
.MakeZero(t
.Elem()))
298 func sendResponse(sending
*sync
.Mutex
, req
*Request
, reply
interface{}, codec ServerCodec
, errmsg
string) {
299 resp
:= new(Response
)
300 // Encode the response header
301 resp
.ServiceMethod
= req
.ServiceMethod
307 err
:= codec
.WriteResponse(resp
, reply
)
309 log
.Println("rpc: writing response:", err
)
314 func (s
*service
) call(sending
*sync
.Mutex
, mtype
*methodType
, req
*Request
, argv
, replyv reflect
.Value
, codec ServerCodec
) {
318 function
:= mtype
.method
.Func
319 // Invoke the method, providing a new value for the reply.
320 returnValues
:= function
.Call([]reflect
.Value
{s
.rcvr
, argv
, replyv
})
321 // The return value for the method is an os.Error.
322 errInter
:= returnValues
[0].Interface()
325 errmsg
= errInter
.(os
.Error
).String()
327 sendResponse(sending
, req
, replyv
.Interface(), codec
, errmsg
)
330 type gobServerCodec
struct {
331 rwc io
.ReadWriteCloser
336 func (c
*gobServerCodec
) ReadRequestHeader(r
*Request
) os
.Error
{
337 return c
.dec
.Decode(r
)
340 func (c
*gobServerCodec
) ReadRequestBody(body
interface{}) os
.Error
{
341 return c
.dec
.Decode(body
)
344 func (c
*gobServerCodec
) WriteResponse(r
*Response
, body
interface{}) os
.Error
{
345 if err
:= c
.enc
.Encode(r
); err
!= nil {
348 return c
.enc
.Encode(body
)
351 func (c
*gobServerCodec
) Close() os
.Error
{
356 // ServeConn runs the server on a single connection.
357 // ServeConn blocks, serving the connection until the client hangs up.
358 // The caller typically invokes ServeConn in a go statement.
359 // ServeConn uses the gob wire format (see package gob) on the
360 // connection. To use an alternate codec, use ServeCodec.
361 func (server
*Server
) ServeConn(conn io
.ReadWriteCloser
) {
362 server
.ServeCodec(&gobServerCodec
{conn
, gob
.NewDecoder(conn
), gob
.NewEncoder(conn
)})
365 // ServeCodec is like ServeConn but uses the specified codec to
366 // decode requests and encode responses.
367 func (server
*Server
) ServeCodec(codec ServerCodec
) {
368 sending
:= new(sync
.Mutex
)
370 // Grab the request header.
372 err
:= codec
.ReadRequestHeader(req
)
374 if err
== os
.EOF || err
== io
.ErrUnexpectedEOF
{
375 if err
== io
.ErrUnexpectedEOF
{
376 log
.Println("rpc:", err
)
380 s
:= "rpc: server cannot decode request: " + err
.String()
381 sendResponse(sending
, req
, invalidRequest
, codec
, s
)
384 serviceMethod
:= strings
.Split(req
.ServiceMethod
, ".", -1)
385 if len(serviceMethod
) != 2 {
386 s
:= "rpc: service/method request ill-formed: " + req
.ServiceMethod
387 sendResponse(sending
, req
, invalidRequest
, codec
, s
)
390 // Look up the request.
392 service
, ok
:= server
.serviceMap
[serviceMethod
[0]]
395 s
:= "rpc: can't find service " + req
.ServiceMethod
396 sendResponse(sending
, req
, invalidRequest
, codec
, s
)
399 mtype
, ok
:= service
.method
[serviceMethod
[1]]
401 s
:= "rpc: can't find method " + req
.ServiceMethod
402 sendResponse(sending
, req
, invalidRequest
, codec
, s
)
405 // Decode the argument value.
406 argv
:= _new(mtype
.argType
)
407 replyv
:= _new(mtype
.replyType
)
408 err
= codec
.ReadRequestBody(argv
.Interface())
410 log
.Println("rpc: tearing down", serviceMethod
[0], "connection:", err
)
411 sendResponse(sending
, req
, replyv
.Interface(), codec
, err
.String())
414 go service
.call(sending
, mtype
, req
, argv
, replyv
, codec
)
419 // Accept accepts connections on the listener and serves requests
420 // for each incoming connection. Accept blocks; the caller typically
421 // invokes it in a go statement.
422 func (server
*Server
) Accept(lis net
.Listener
) {
424 conn
, err
:= lis
.Accept()
426 log
.Exit("rpc.Serve: accept:", err
.String()) // TODO(r): exit?
428 go server
.ServeConn(conn
)
432 // Register publishes in the DefaultServer the set of methods
433 // of the receiver value that satisfy the following conditions:
435 // - two arguments, both pointers to exported structs
436 // - one return value, of type os.Error
437 // It returns an error if the receiver is not an exported type or has no
439 func Register(rcvr
interface{}) os
.Error
{ return DefaultServer
.Register(rcvr
) }
441 // A ServerCodec implements reading of RPC requests and writing of
442 // RPC responses for the server side of an RPC session.
443 // The server calls ReadRequestHeader and ReadRequestBody in pairs
444 // to read requests from the connection, and it calls WriteResponse to
445 // write a response back. The server calls Close when finished with the
447 type ServerCodec
interface {
448 ReadRequestHeader(*Request
) os
.Error
449 ReadRequestBody(interface{}) os
.Error
450 WriteResponse(*Response
, interface{}) os
.Error
455 // ServeConn runs the DefaultServer on a single connection.
456 // ServeConn blocks, serving the connection until the client hangs up.
457 // The caller typically invokes ServeConn in a go statement.
458 // ServeConn uses the gob wire format (see package gob) on the
459 // connection. To use an alternate codec, use ServeCodec.
460 func ServeConn(conn io
.ReadWriteCloser
) {
461 DefaultServer
.ServeConn(conn
)
464 // ServeCodec is like ServeConn but uses the specified codec to
465 // decode requests and encode responses.
466 func ServeCodec(codec ServerCodec
) {
467 DefaultServer
.ServeCodec(codec
)
470 // Accept accepts connections on the listener and serves requests
471 // to DefaultServer for each incoming connection.
472 // Accept blocks; the caller typically invokes it in a go statement.
473 func Accept(lis net
.Listener
) { DefaultServer
.Accept(lis
) }
475 // Can connect to RPC service using HTTP CONNECT to rpcPath.
476 var connected
= "200 Connected to Go RPC"
478 // ServeHTTP implements an http.Handler that answers RPC requests.
479 func (server
*Server
) ServeHTTP(w http
.ResponseWriter
, req
*http
.Request
) {
480 if req
.Method
!= "CONNECT" {
481 w
.SetHeader("Content-Type", "text/plain; charset=utf-8")
482 w
.WriteHeader(http
.StatusMethodNotAllowed
)
483 io
.WriteString(w
, "405 must CONNECT\n")
486 conn
, _
, err
:= w
.Hijack()
488 log
.Print("rpc hijacking ", w
.RemoteAddr(), ": ", err
.String())
491 io
.WriteString(conn
, "HTTP/1.0 "+connected
+"\n\n")
492 server
.ServeConn(conn
)
495 // HandleHTTP registers an HTTP handler for RPC messages on rpcPath,
496 // and a debugging handler on debugPath.
497 // It is still necessary to invoke http.Serve(), typically in a go statement.
498 func (server
*Server
) HandleHTTP(rpcPath
, debugPath
string) {
499 http
.Handle(rpcPath
, server
)
500 http
.Handle(debugPath
, debugHTTP
{server
})
503 // HandleHTTP registers an HTTP handler for RPC messages to DefaultServer
504 // on DefaultRPCPath and a debugging handler on DefaultDebugPath.
505 // It is still necessary to invoke http.Serve(), typically in a go statement.
507 DefaultServer
.HandleHTTP(DefaultRPCPath
, DefaultDebugPath
)