rpcgen使用

本文给出一个rpcgen自定义数据结构的使用例子。

msg.x文件内容如下:

/* msg.x: Remote msg printing protocol */

struct request {
    int user;
    char command[32];
};

struct calendar {
    int Year;  
    char Month;
    char Day;
    char Hour;
    char Min;
    char Sec;
};

 program MESSAGEPROG {
     version PRINTMESSAGEVERS {
        struct calendar GETTIME(struct request*) = 1;
 	 } = 1;
} = 0x20000001;

运行命令rpcgen msg.x生成msg_clnt.c、msg.h、msg_svc.c、msg_xdr.c四个文件。其中msg.h和msg_xdr.c是客户端和服务器共用的。msg_clnt.c是客户端代码,msg_svc.c是服务器端代码。几个文件内容分别如下:

msg_clnt.c

/*
 * Please do not edit this file.
 * It was generated using rpcgen.
 */

#include <memory.h> /* for memset */
#include "msg.h"

/* Default timeout can be changed using clnt_control() */
static struct timeval TIMEOUT = { 25, 0 };

struct calendar *
gettime_1(struct request *argp, CLIENT *clnt)
{
	static struct calendar clnt_res;

	memset((char *)&clnt_res, 0, sizeof(clnt_res));
	if (clnt_call (clnt, GETTIME,
		(xdrproc_t) xdr_request, (caddr_t) argp,
		(xdrproc_t) xdr_calendar, (caddr_t) &clnt_res,
		TIMEOUT) != RPC_SUCCESS) {
		return (NULL);
	}
	return (&clnt_res);
}

msg.h

/*
 * Please do not edit this file.
 * It was generated using rpcgen.
 */

#ifndef _MSG_H_RPCGEN
#define _MSG_H_RPCGEN

#include <rpc/rpc.h>


#ifdef __cplusplus
extern "C" {
#endif


struct request {
	int user;
	char command[32];
};
typedef struct request request;

struct calendar {
	int Year;
	char Month;
	char Day;
	char Hour;
	char Min;
	char Sec;
};
typedef struct calendar calendar;

#define MESSAGEPROG 0x20000001
#define PRINTMESSAGEVERS 1

#if defined(__STDC__) || defined(__cplusplus)
#define GETTIME 1
extern  struct calendar * gettime_1(struct request *, CLIENT *);
extern  struct calendar * gettime_1_svc(struct request *, struct svc_req *);
extern int messageprog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);

#else /* K&R C */
#define GETTIME 1
extern  struct calendar * gettime_1();
extern  struct calendar * gettime_1_svc();
extern int messageprog_1_freeresult ();
#endif /* K&R C */

/* the xdr functions */

#if defined(__STDC__) || defined(__cplusplus)
extern  bool_t xdr_request (XDR *, request*);
extern  bool_t xdr_calendar (XDR *, calendar*);

#else /* K&R C */
extern bool_t xdr_request ();
extern bool_t xdr_calendar ();

#endif /* K&R C */

#ifdef __cplusplus
}
#endif

#endif /* !_MSG_H_RPCGEN */

msg_svc.c

/*
 * Please do not edit this file.
 * It was generated using rpcgen.
 */

#include "msg.h"
#include <stdio.h>
#include <stdlib.h>
#include <rpc/pmap_clnt.h>
#include <string.h>
#include <memory.h>
#include <sys/socket.h>
#include <netinet/in.h>

#ifndef SIG_PF
#define SIG_PF void(*)(int)
#endif

static void
messageprog_1(struct svc_req *rqstp, register SVCXPRT *transp)
{
	union {
		struct request gettime_1_arg;
	} argument;
	char *result;
	xdrproc_t _xdr_argument, _xdr_result;
	char *(*local)(char *, struct svc_req *);

	switch (rqstp->rq_proc) {
	case NULLPROC:
		(void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL);
		return;

	case GETTIME:
		_xdr_argument = (xdrproc_t) xdr_request;
		_xdr_result = (xdrproc_t) xdr_calendar;
		local = (char *(*)(char *, struct svc_req *)) gettime_1_svc;
		break;

	default:
		svcerr_noproc (transp);
		return;
	}
	memset ((char *)&argument, 0, sizeof (argument));
	if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
		svcerr_decode (transp);
		return;
	}
	result = (*local)((char *)&argument, rqstp);
	if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) {
		svcerr_systemerr (transp);
	}
	if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
		fprintf (stderr, "%s", "unable to free arguments");
		exit (1);
	}
	return;
}

int
main (int argc, char **argv)
{
	register SVCXPRT *transp;

	pmap_unset (MESSAGEPROG, PRINTMESSAGEVERS);

	transp = svcudp_create(RPC_ANYSOCK);
	if (transp == NULL) {
		fprintf (stderr, "%s", "cannot create udp service.");
		exit(1);
	}
	if (!svc_register(transp, MESSAGEPROG, PRINTMESSAGEVERS, messageprog_1, IPPROTO_UDP)) {
		fprintf (stderr, "%s", "unable to register (MESSAGEPROG, PRINTMESSAGEVERS, udp).");
		exit(1);
	}

	transp = svctcp_create(RPC_ANYSOCK, 0, 0);
	if (transp == NULL) {
		fprintf (stderr, "%s", "cannot create tcp service.");
		exit(1);
	}
	if (!svc_register(transp, MESSAGEPROG, PRINTMESSAGEVERS, messageprog_1, IPPROTO_TCP)) {
		fprintf (stderr, "%s", "unable to register (MESSAGEPROG, PRINTMESSAGEVERS, tcp).");
		exit(1);
	}

	svc_run ();
	fprintf (stderr, "%s", "svc_run returned");
	exit (1);
	/* NOTREACHED */
}

msg_xdr.c

/*
 * Please do not edit this file.
 * It was generated using rpcgen.
 */

#include "msg.h"

bool_t
xdr_request (XDR *xdrs, request *objp)
{
	register int32_t *buf;

	int i;
	 if (!xdr_int (xdrs, &objp->user))
		 return FALSE;
	 if (!xdr_vector (xdrs, (char *)objp->command, 32,
		sizeof (char), (xdrproc_t) xdr_char))
		 return FALSE;
	return TRUE;
}

bool_t
xdr_calendar (XDR *xdrs, calendar *objp)
{
	register int32_t *buf;

	 if (!xdr_int (xdrs, &objp->Year))
		 return FALSE;
	 if (!xdr_char (xdrs, &objp->Month))
		 return FALSE;
	 if (!xdr_char (xdrs, &objp->Day))
		 return FALSE;
	 if (!xdr_char (xdrs, &objp->Hour))
		 return FALSE;
	 if (!xdr_char (xdrs, &objp->Min))
		 return FALSE;
	 if (!xdr_char (xdrs, &objp->Sec))
		 return FALSE;
	return TRUE;
}

对于客户端,我们自己编写的代码如下client.c:

#include <stdio.h>
#include "msg.h"

#define	RMACHINE	"localhost"	/* name of remote machine	*/
CLIENT	*handle;			/* handle for remote procedure	*/

//gettime_1是rpcgen自动生成的函数。这里封装一下,使我们自己调用的函数原型保持不变
struct calendar * gettime(struct request *req)
{
    return gettime_1(req, handle);
}

int main(char *argc, char **argv)
{
	struct request req;
	struct calendar *calendar;
	int ret;

	req.user = 2;
	sprintf(req.command, "gettime");

    //create handle
	handle = clnt_create(RMACHINE, MESSAGEPROG, PRINTMESSAGEVERS, "tcp");
	if (handle == (CLIENT *)NULL) {
		perror("clnt_create");
		return 0;
	}

	calendar = gettime(&req);
	printf("time %d-%d-%d %d:%d:%d\n", calendar->Year, calendar->Month, calendar->Day, 
	 		calendar->Hour, calendar->Min, calendar->Sec);

	clnt_destroy(handle);
	exit(0);
}

对于服务器端主函数的流程rpcgen已经帮我自动实现了,我们只需要实现对应客户端请求的响应函数就可以了。我们自己编写的服务器端代码如下,msg_sif.c:

/* Server-side stub inteface routines written by hand */
#include <rpc/rpc.h>

#define	RPC_SVC
#include "msg.h"

struct calendar * gettime_1_svc(struct request *req, struct svc_req *rqstp)
{
    static struct calendar cal;

    printf("user=%d,command=%s\n", req->user, req->command);
	cal.Year = 2021;
    cal.Month = 8;
    cal.Day = 13;
    cal.Hour = 19;
    cal.Min = 04;
    cal.Sec = 30;
	return &cal;
}

方便编译,自己写了个Makefile如下:

all:
	cc  msg_clnt.c msg.h client.c msg_xdr.c -o client -lnsl
	cc  msg_svc.c msg.h msg_xdr.c msg_sif.c -o server -lnsl

测试效果如下。先运行服务器:

./server

接着运行客户端:

$ ./client 
time 2021-8-13 19:4:30 

服务器端打印:

$ ./server 
user=2,command=gettime

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值