📄 rpc.prog.ms
字号:
You will be given a unique program number in return..IX RPC administration.IX administration "of RPC".LPThe RPC program numbers and protocol specifications of standard Sun RPC services can befound in the include files in .I "/usr/include/rpcsvc" .These services, however, constitute only a small subset of those which have been registered. The complete list of registered programs, as of the time when this manual was printed, is:.LP\fBTable 3-2\fI RPC Registered Programs\fR.TS Hbox tab (&) ;lfBI lfBI lfBIlfL lfL lfI .RPC Number&Program&Description_.TH.sp.5100000&PMAPPROG&portmapper100001&RSTATPROG&remote stats 100002&RUSERSPROG&remote users 100003&NFSPROG&nfs 100004&YPPROG&Yellow Pages 100005&MOUNTPROG&mount demon 100006&DBXPROG&remote dbx 100007&YPBINDPROG&yp binder 100008&WALLPROG&shutdown msg 100009&YPPASSWDPROG&yppasswd server 100010ÐERSTATPROGðer stats 100011&RQUOTAPROG&disk quotas 100012&SPRAYPROG&spray packets 100013&IBM3270PROG&3270 mapper 100014&IBMRJEPROG&RJE mapper 100015&SELNSVCPROG&selection service 100016&RDATABASEPROG&remote database access 100017&REXECPROG&remote execution 100018&ALICEPROG&Alice Office Automation 100019&SCHEDPROG&scheduling service 100020&LOCKPROG&local lock manager 100021&NETLOCKPROG&network lock manager 100022&X25PROG&x.25 inr protocol 100023&STATMON1PROG&status monitor 1 100024&STATMON2PROG&status monitor 2 100025&SELNLIBPROG&selection library 100026&BOOTPARAMPROG&boot parameters service 100027&MAZEPROG&mazewars game 100028&YPUPDATEPROG&yp update 100029&KEYSERVEPROG&key server 100030&SECURECMDPROG&secure login 100031&NETFWDIPROG&nfs net forwarder init 100032&NETFWDTPROG&nfs net forwarder trans 100033&SUNLINKMAP_PROG&sunlink MAP 100034&NETMONPROG&network monitor 100035&DBASEPROG&lightweight database 100036&PWDAUTHPROG&password authorization 100037&TFSPROG&translucent file svc 100038&NSEPROG&nse server 100039&NSE_ACTIVATE_PROG&nse activate daemon .sp .2i150001&PCNFSDPROG&pc passwd authorization .sp .2i200000&PYRAMIDLOCKINGPROG&Pyramid-locking 200001&PYRAMIDSYS5&Pyramid-sys5 200002&CADDS_IMAGE&CV cadds_image .sp .2i300001&ADT_RFLOCKPROG&ADT file locking .TE.NH 2\&Passing Arbitrary Data Types.IX "arbitrary data types".LPIn the previous example, the RPC call passes a single.I "unsigned long"RPC can handle arbitrary data structures, regardless ofdifferent machines' byte orders or structure layout conventions,by always converting them to a network standard called.I "External Data Representation"(XDR) beforesending them over the wire.The process of converting from a particular machine representationto XDR format is called.I serializing ,and the reverse process is called.I deserializing .The type field parameters of.I callrpc() and.I registerrpc() can be a built-in procedure like.I xdr_u_long() in the previous example, or a user supplied one.XDR has these built-in type routines:.IX RPC "built-in routines".DS.ft CWxdr_int() xdr_u_int() xdr_enum()xdr_long() xdr_u_long() xdr_bool()xdr_short() xdr_u_short() xdr_wrapstring()xdr_char() xdr_u_char().DENote that the routine.I xdr_string() exists, but cannot be used with .I callrpc() and.I registerrpc (),which only pass two parameters to their XDR routines..I xdr_wrapstring() has only two parameters, and is thus OK. It calls .I xdr_string ()..LPAs an example of a user-defined type routine,if you wanted to send the structure.DS.ft CWstruct simple { int a; short b;} simple;.DEthen you would call.I callrpc() as.DS.ft CWcallrpc(hostname, PROGNUM, VERSNUM, PROCNUM, xdr_simple, &simple ...);.DEwhere.I xdr_simple() is written as:.ie t .DS.el .DS L.ft CW#include <rpc/rpc.h>xdr_simple(xdrsp, simplep) XDR *xdrsp; struct simple *simplep;{ if (!xdr_int(xdrsp, &simplep->a)) return (0); if (!xdr_short(xdrsp, &simplep->b)) return (0); return (1);}.DE.LPAn XDR routine returns nonzero (true in the sense of C) if it completes successfully, and zero otherwise.A complete description of XDR is in the.I "XDR Protocol Specification" section of this manual, only few implementation examples are given here..LPIn addition to the built-in primitives,there are also the prefabricated building blocks:.DS.ft CWxdr_array() xdr_bytes() xdr_reference()xdr_vector() xdr_union() xdr_pointer()xdr_string() xdr_opaque().DETo send a variable array of integers,you might package them up as a structure like this.DS.ft CWstruct varintarr { int *data; int arrlnth;} arr;.DEand make an RPC call such as.DS.ft CWcallrpc(hostname, PROGNUM, VERSNUM, PROCNUM, xdr_varintarr, &arr...);.DEwith.I xdr_varintarr() defined as:.ie t .DS.el .DS L.ft CWxdr_varintarr(xdrsp, arrp) XDR *xdrsp; struct varintarr *arrp;{ return (xdr_array(xdrsp, &arrp->data, &arrp->arrlnth, MAXLEN, sizeof(int), xdr_int));}.DEThis routine takes as parameters the XDR handle,a pointer to the array, a pointer to the size of the array,the maximum allowable array size,the size of each array element,and an XDR routine for handling each array element..KS.LPIf the size of the array is known in advance, one can use.I xdr_vector (),which serializes fixed-length arrays..ie t .DS.el .DS L.ft CWint intarr[SIZE];xdr_intarr(xdrsp, intarr) XDR *xdrsp; int intarr[];{ int i; return (xdr_vector(xdrsp, intarr, SIZE, sizeof(int), xdr_int));}.DE.KE.LPXDR always converts quantities to 4-byte multiples when serializing.Thus, if either of the examples above involved charactersinstead of integers, each character would occupy 32 bits.That is the reason for the XDR routine.I xdr_bytes()which is like.I xdr_array()except that it packs characters;.I xdr_bytes() has four parameters, similar to the first four parameters of.I xdr_array ().For null-terminated strings, there is also the.I xdr_string()routine, which is the same as.I xdr_bytes() without the length parameter.On serializing it gets the string length from.I strlen (),and on deserializing it creates a null-terminated string..LPHere is a final example that calls the previously written.I xdr_simple() as well as the built-in functions.I xdr_string() and.I xdr_reference (),which chases pointers:.ie t .DS.el .DS L.ft CWstruct finalexample { char *string; struct simple *simplep;} finalexample;xdr_finalexample(xdrsp, finalp) XDR *xdrsp; struct finalexample *finalp;{ if (!xdr_string(xdrsp, &finalp->string, MAXSTRLEN)) return (0); if (!xdr_reference(xdrsp, &finalp->simplep, sizeof(struct simple), xdr_simple); return (0); return (1);}.DENote that we could as easily call.I xdr_simple() here instead of.I xdr_reference ()..NH 1\&Lowest Layer of RPC.IX "lowest layer of RPC".IX "RPC" "lowest layer".LPIn the examples given so far,RPC takes care of many details automatically for you.In this section, we'll show you how you can change the defaultsby using lower layers of the RPC library.It is assumed that you are familiar with socketsand the system calls for dealing with them..LPThere are several occasions when you may need to use lower layers of RPC. First, you may need to use TCP, since the higher layer uses UDP, which restricts RPC calls to 8K bytes of data. Using TCP permits calls to send long streams of data. For an example, see the.I TCPsection below. Second, you may want to allocate and free memorywhile serializing or deserializing with XDR routines. There is no call at the higher level to let you free memory explicitly. For more explanation, see the.I "Memory Allocation with XDR"section below. Third, you may need to perform authentication on either the client or server side, by supplying credentials or verifying them.See the explanation in the .I Authenticationsection below..NH 2\&More on the Server Side.IX RPC "server side".LPThe server for the.I nusers() program shown below does the same thing as the one using.I registerrpc() above, but is written using a lower layer of the RPC package:.ie t .DS.el .DS L.ft CW#include <stdio.h>#include <rpc/rpc.h>#include <utmp.h>#include <rpcsvc/rusers.h>main(){ SVCXPRT *transp; int nuser(); transp = svcudp_create(RPC_ANYSOCK); if (transp == NULL){ fprintf(stderr, "can't create an RPC server\en"); exit(1); } pmap_unset(RUSERSPROG, RUSERSVERS); if (!svc_register(transp, RUSERSPROG, RUSERSVERS, nuser, IPPROTO_UDP)) { fprintf(stderr, "can't register RUSER service\en"); exit(1); } svc_run(); /* \fINever returns\fP */ fprintf(stderr, "should never reach this point\en");}nuser(rqstp, transp) struct svc_req *rqstp; SVCXPRT *transp;{ unsigned long nusers; switch (rqstp->rq_proc) { case NULLPROC: if (!svc_sendreply(transp, xdr_void, 0)) fprintf(stderr, "can't reply to RPC call\en"); return; case RUSERSPROC_NUM:.ft I /* * Code here to compute the number of users * and assign it to the variable \fInusers\fP */.ft CW if (!svc_sendreply(transp, xdr_u_long, &nusers)) fprintf(stderr, "can't reply to RPC call\en"); return; default: svcerr_noproc(transp); return; }}.DE.LPFirst, the server gets a transport handle, which is usedfor receiving and replying to RPC messages..I registerrpc() uses.I svcudp_create()to get a UDP handle.If you require a more reliable protocol, call.I svctcp_create()instead.If the argument to.I svcudp_create() is.I RPC_ANYSOCKthe RPC library creates a socketon which to receive and reply to RPC calls. Otherwise,.I svcudp_create() expects its argument to be a valid socket number.If you specify your own socket, it can be bound or unbound.If it is bound to a port by the user, the port numbers of.I svcudp_create() and.I clnttcp_create()(the low-level client routine) must match..LPIf the user specifies the.I RPC_ANYSOCK argument, the RPC library routines will open sockets.Otherwise they will expect the user to do so. The routines.I svcudp_create() and .I clntudp_create()will cause the RPC library routines to.I bind() their socket if it is not bound already..LPA service may choose to register its port number with thelocal portmapper service. This is done is done by specifyinga non-zero protocol number in.I svc_register ().Incidently, a client can discover the server's port number by consulting the portmapper on their server's machine. This can be done automatically by specifying a zero port number in .I clntudp_create() or.I clnttcp_create ()..LPAfter creating an.I SVCXPRT ,the next step is to call.I pmap_unset()so that if the.I nusers() server crashed earlier,any previous trace of it is erased before restarting.More precisely,.I pmap_unset() erases the entry for.I RUSERSPROGfrom the port mapper's tables..LPFinally, we associate the program number for.I nusers() with the procedure.I nuser ().The final argument to.I svc_register() is normally the protocol being used,which, in this case, is.I IPPROTO_UDPNotice that unlike.I registerrpc (),there are no XDR routines involvedin the registration process.Also, registration is done on the program,rather than procedure, level..LPThe user routine.I nuser() must call and dispatch the appropriate XDR routinesbased on the procedure number.Note thattwo things are handled by.I nuser() that.I registerrpc() handles automatically.The first is that procedure.I NULLPROC(currently zero) returns with no results.This can be used as a simple testfor detecting if a remote program is running.Second, there is a check for invalid procedure numbers.If one is detected,.I svcerr_noproc()is called to handle the error..KS.LPThe user service routine serializes the results and returnsthem to the RPC caller via.I svc_sendreply()Its first parameter is the.I SVCXPRThandle, the second is the XDR routine,and the third is a pointer to the data to be returned.Not illustrated above is how a serverhandles an RPC program that receives data.As an example, we can add a procedure.I RUSERSPROC_BOOLwhich has an argument.I nusers (),and returns.I TRUE or.I FALSE depending on whether there are nusers logged on.It would look like this:.ie t .DS.el .DS L.ft CWcase RUSERSPROC_BOOL: { int bool; unsigned nuserquery; if (!svc_getargs(transp, xdr_u_int, &nuserquery) { svcerr_decode(transp); return; }.ft I /* * Code to set \fInusers\fP = number of users */.ft CW if (nuserquery == nusers)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -