⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rpcgen.ms

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 MS
📖 第 1 页 / 共 3 页
字号:
.I FOO_svc.c ..LPNow we're ready to have some fun.  First, copy the server to aremote machine and run it.  For this  example,  themachine is called \*Qmoon\*U.  Server processes are run in thebackground, because they never exit..ie t .DS.el .DS L.ft CWmoon% \fBmsg_server &\fP	       .DEThen on our local machine (\*Qsun\*U) we can print a message on \*Qmoon\*Usconsole..ie t .DS.el .DS L.ft CWsun% \fBprintmsg moon "Hello, moon."\fP.DEThe message will get printed to \*Qmoon\*Us console.  You can print amessage on anybody's console (including your own) with this program ifyou are able to copy the server to their machine and run it..NH 1\&Generating XDR Routines.IX RPC "generating XDR routines".LPThe previous example  only demonstrated  the  automatic generation ofclient  and server RPC  code. .I rpcgen may also  be used to generate XDR routines, that  is,  the routinesnecessary to  convert   local  datastructures into network format and vice-versa.  This example presentsa complete RPC service\(ema remote directory listing service, which uses.I rpcgennot  only  to generate stub routines, but also to  generate  the XDRroutines.  Here is the protocol description file:.ie t .DS.el .DS L.ft I/* * dir.x: Remote directory listing protocol */.ft CWconst MAXNAMELEN = 255;		/* \fImaximum length of a directory entry\fP */typedef string nametype<MAXNAMELEN>;	/* \fIa directory entry\fP */typedef struct namenode *namelist;		/* \fIa link in the listing\fP */.ft I/* * A node in the directory listing */.ft CWstruct namenode {	nametype name;		/* \fIname of directory entry\fP */	namelist next;		/* \fInext entry\fP */};.ft I/* * The result of a READDIR operation. */.ft CWunion readdir_res switch (int errno) {case 0:	namelist list;	/* \fIno error: return directory listing\fP */default:	void;		/* \fIerror occurred: nothing else to return\fP */};.ft I/* * The directory program definition */.ft CWprogram DIRPROG {	version DIRVERS {		readdir_res		READDIR(nametype) = 1;	} = 1;} = 76;.DE.SHNote:.ITypes (like.I readdir_res in the example above) can be defined usingthe \*Qstruct\*U, \*Qunion\*U and \*Qenum\*U keywords, but those keywordsshould not be used in subsequent declarations of variables of those types.For example, if you define a union \*Qfoo\*U, you should declare usingonly \*Qfoo\*U and not \*Qunion foo\*U.  In fact,.I rpcgen compilesRPC unions into C structures and it is an error to declare them using the\*Qunion\*U keyword..LPRunning .I rpcgen on .I dir.x creates four output files.  Three are the same as before: header file,client stub routines and server skeleton.  The fourth are the XDR routinesnecessary for converting the data types we declared into XDR format andvice-versa.  These are output in the file.I dir_xdr.c ..LPHere is the implementation of the.I READDIR procedure..ie t .DS.el .DS L.vs 11.ft I/* * dir_proc.c: remote readdir implementation */.ft CW#include <rpc/rpc.h>#include <sys/dir.h>#include "dir.h"extern int errno;extern char *malloc();extern char *strdup();readdir_res *readdir_1(dirname)	nametype *dirname;{	DIR *dirp;	struct direct *d;	namelist nl;	namelist *nlp;	static readdir_res res; /* \fImust be static\fP! */.ft I	/*	 * Open directory	 */.ft CW	dirp = opendir(*dirname);	if (dirp == NULL) {		res.errno = errno;		return (&res);	}.ft I	/*	 * Free previous result	 */.ft CW	xdr_free(xdr_readdir_res, &res);.ft I	/*	 * Collect directory entries.	 * Memory allocated here will be freed by \fIxdr_free\fP	 * next time \fIreaddir_1\fP is called	 */.ft CW	nlp = &res.readdir_res_u.list;	while (d = readdir(dirp)) {		nl = *nlp = (namenode *) malloc(sizeof(namenode));		nl->name = strdup(d->d_name);		nlp = &nl->next;	}	*nlp = NULL;.ft I	/*	 * Return the result	 */.ft CW	res.errno = 0;	closedir(dirp);	return (&res);}.vs.DEFinally, there is the client side program to call the server:.ie t .DS.el .DS L.ft I/* * rls.c: Remote directory listing client */.ft CW#include <stdio.h>#include <rpc/rpc.h>	/* \fIalways need this\fP */#include "dir.h"		/* \fIwill be generated by rpcgen\fI */extern int errno;main(argc, argv)	int argc;	char *argv[];{	CLIENT *cl;	char *server;	char *dir;	readdir_res *result;	namelist nl;	if (argc != 3) {		fprintf(stderr, "usage: %s host directory\en", 		  argv[0]);		exit(1);	}.ft I	/*	 * Remember what our command line arguments refer to	 */.ft CW	server = argv[1];	dir = argv[2];.ft I	/*	 * Create client "handle" used for calling \fIMESSAGEPROG\fP on the	 * server designated on the command line. We tell the RPC package	 * to use the "tcp" protocol when contacting the server.	 */.ft CW	cl = clnt_create(server, DIRPROG, DIRVERS, "tcp");	if (cl == NULL) {.ft I		/*		 * Couldn't establish connection with server.		 * Print error message and die.		 */.ft CW		clnt_pcreateerror(server);		exit(1);	}.ft I	/*	 * Call the remote procedure \fIreaddir\fP on the server	 */.ft CW	result = readdir_1(&dir, cl);	if (result == NULL) {.ft I		/*		 * An error occurred while calling the server. 	 	 * Print error message and die.		 */.ft CW		clnt_perror(cl, server);		exit(1);	}.ft I	/*	 * Okay, we successfully called the remote procedure.	 */.ft CW	if (result->errno != 0) {.ft I		/*		 * A remote system error occurred.		 * Print error message and die.		 */.ft CW		errno = result->errno;		perror(dir);		exit(1);	}.ft I	/*	 * Successfully got a directory listing.	 * Print it out.	 */.ft CW	for (nl = result->readdir_res_u.list; nl != NULL; 	  nl = nl->next) {		printf("%s\en", nl->name);	}	exit(0);}.DECompile everything, and run..DS.ft CWsun%  \fBrpcgen dir.x\fPsun%  \fBcc rls.c dir_clnt.c dir_xdr.c -o rls\fPsun%  \fBcc dir_svc.c dir_proc.c dir_xdr.c -o dir_svc\fPsun%  \fBdir_svc &\fPmoon%  \fBrls sun /usr/pub\fP\&.\&..asciieqnchargreekkbdmarg8tabclrtabstabs4moon%.DE.LP.IX "debugging with rpcgen" "" "debugging with \fIrpcgen\fP"A final note about .I rpcgen :The client program and the server procedure can be tested together as a single program by simply linking them with each other rather than with the client and server stubs.  The procedure calls will beexecuted as ordinary local procedure calls and the program can be debugged with a local debugger such as .I dbx .When the program is working, the client program can be linked to the client stub produced by .I rpcgen and the server procedures can be linked to the server stub producedby .I rpcgen ..SH.I NOTE :\fIIf you do this, you may want to comment out calls to RPC libraryroutines, and have client-side routines call server routinesdirectly.\fP.LP.NH 1\&The C-Preprocessor.IX rpcgen "C-preprocessor" \fIrpcgen\fP.LPThe C-preprocessor is  run on all input  files before they arecompiled, so all the preprocessor directives are legal within a \*Q.x\*Ufile. Four symbols may be defined, depending upon which output file isgetting generated. The symbols are:.TSbox tab (&);lfI lfIlfL l .Symbol&Usage_RPC_HDR&for header-file outputRPC_XDR&for XDR routine outputRPC_SVC&for server-skeleton outputRPC_CLNT&for client stub output.TE.LPAlso, .I rpcgen does  a little preprocessing   of its own. Any  line thatbegins  with  a percent sign is passed  directly into the output file,without any interpretation of the line.  Here is a simple example thatdemonstrates the preprocessing features..ie t .DS.el .DS L.ft I/* * time.x: Remote time protocol */.ft CWprogram TIMEPROG {        version TIMEVERS {                unsigned int TIMEGET(void) = 1;        } = 1;} = 44;#ifdef RPC_SVC%int *%timeget_1()%{%        static int thetime;%%        thetime = time(0);%        return (&thetime);%}#endif.DEThe '%' feature is not generally recommended, as there is no guaranteethat the compiler will stick the output where you intended..NH 1\&\fBrpcgen\fP Programming Notes.IX rpcgen "other operations" \fIrpcgen\fP.sp .NH 2\&Timeout Changes.IX rpcgen "timeout changes" \fIrpcgen\fP.LPRPC sets a default timeout of 25 seconds for RPC calls when.I clnt_create()is used.  This timeout may be changed using.I clnt_control()Here is a small code fragment to demonstrate use of.I clnt_control ():.IDstruct timeval tv;CLIENT *cl;.sp .5cl = clnt_create("somehost", SOMEPROG, SOMEVERS, "tcp");if (cl == NULL) {	exit(1);}tv.tv_sec = 60;	/* \fIchange timeout to 1 minute\fP */tv.tv_usec = 0;clnt_control(cl, CLSET_TIMEOUT, &tv);	.DE.NH 2\&Handling Broadcast on the Server Side.IX "broadcast RPC".IX rpcgen "broadcast RPC" \fIrpcgen\fP.LPWhen a procedure is known to be called via broadcast RPC,it is usually wise for the server to not reply unless it can providesome useful information to the client.  This prevents the networkfrom getting flooded by useless replies..LPTo prevent the server from replying, a remote procedure canreturn NULL as its result, and the server code generated by.I rpcgen will detect this and not send out a reply..LPHere is an example of a procedure that replies only if itthinks it is an NFS server:.IDvoid *reply_if_nfsserver(){	char notnull;	/* \fIjust here so we can use its address\fP */.sp .5	if (access("/etc/exports", F_OK) < 0) {		return (NULL);	/* \fIprevent RPC from replying\fP */	}.ft I

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -