远程过程调用:门和Sun RPC

发布时间 2023-12-21 10:30:48作者: eiSouthBoy

一、门

门提供了调用同一台主机上的另外一个进程中某个过程的能力。门是一种特殊类型的IPC,因为客户端和服务器之间以函数参数和返回值形式交换信息。

示意图:

本想验证书中源码,发现头文件:#include <door.h> 都没有,互联网上查了很久,也没有相关的信息。暂且作罢。。。

二、Sun RPC

远程过程调用(Remote Procedure Call,简称RPC):被调用过程和调用过程处于不同的进程中。RPC通常允许一台主机上的某个客户调用另外一台主机上的某个服务器过程,只要这两台主机以某种形式的网络连接着。

远程过程调用可能是同步的,也可能是异步的。

示意图;

通过RPC实现客户端向服务端调用过程请求,服务器返回一个响应结果。但对于用户来说隐藏了底层网络通讯细节,仅给定服务器的ip即可。

计算器

  • 编写calculator.x文件
/* 
 * filename: calculator.x 
 * function: 定义远程调用中常量、非标准数据类型以及调用过程
 */

const ADD = 0;
const SUB = 1;
const MUL = 2;
const DIV = 3;

struct CALCULATOR
{
    int op; /* 0-ADD, 1-SUB, 2-MUL, 3-DIV */
    float arg1;
    float arg2;
    float result;
};

program CALCULATOR_PROG
{
    version CALCULATOR_VER
    {
        struct CALCULATOR CALCULATOR_PROC(struct CALCULATOR) = 1;
    } = 1;  /*  版本号=1 */
} = 0x20000001; /* RPC程序编号 */
  • rpcgen编译calculator.x文件

命令:rpcgen -a calculator.x

  • 修改文件 calculator_server.c (注意:这个文件不是用户自己创建的,而是由rpcgen编译.x文件时创建的)
/*
 * This is sample code generated by rpcgen.
 * These are only templates and you can use them
 * as a guideline for developing your own functions.
 */

#include "calculator.h"

struct CALCULATOR *
calculator_proc_1_svc(struct CALCULATOR *argp, struct svc_req *rqstp)
{
	static struct CALCULATOR  result;

	/*
	 * insert server code here
	 */
	/* -<<< Add to test*/
	switch (argp->op)
	{
	case ADD:
		result.result = argp->arg1 + argp->arg2;
		break;
	case SUB:
		result.result = argp->arg1 - argp->arg2;
		break;
	case MUL:
		result.result = argp->arg1 * argp->arg2;
		break;
	case DIV:
		result.result = argp->arg1 / argp->arg2;
		break;
	default:
		break;
	}
	/* -<<< Add to test*/

	return &result;
}

  • 修改文件 calculator_client.c (注意:这个文件不是用户自己创建的,而是由rpcgen编译.x文件时创建的)
/*
 * This is sample code generated by rpcgen.
 * These are only templates and you can use them
 * as a guideline for developing your own functions.
 */

#include "calculator.h"


void
calculator_prog_1(char *host)
{
	CLIENT *clnt;
	struct CALCULATOR  *result_1;
	struct CALCULATOR  calculator_proc_1_arg;

#ifndef	DEBUG
	clnt = clnt_create (host, CALCULATOR_PROG, CALCULATOR_VER, "udp");
	if (clnt == NULL) {
		clnt_pcreateerror (host);
		exit (1);
	}
#endif	/* DEBUG */

	/* -<<< Add to test*/
	char c;
	printf("choose the operation:\n\t0---ADD\n\t1---SUB\n\t2---MUL\n\t3---DIV\n");
	c = getchar();
	if (c > '3' && c < '0')
	{
		printf("error:operate/n");
		exit(1);
	}
	calculator_proc_1_arg.op = c - '0';
	printf("input the first number:");
	scanf("%f", &calculator_proc_1_arg.arg1);
	printf("input the second number:");
	scanf("%f", &calculator_proc_1_arg.arg2);
	/* -<<< Add to test*/

	result_1 = calculator_proc_1(&calculator_proc_1_arg, clnt);
	if (result_1 == (struct CALCULATOR *)NULL)
	{
		clnt_perror(clnt, "call failed");
	}
#ifndef DEBUG
	clnt_destroy(clnt);
#endif /* DEBUG */

	/* -<<< Add to test*/
	printf("The Result is %.3f \n", result_1->result);
	/* -<<< Add to test*/
}


int
main (int argc, char *argv[])
{
	char *host;

	if (argc < 2) {
		printf ("usage: %s server_host\n", argv[0]);
		exit (1);
	}
	host = argv[1];
	calculator_prog_1 (host);
exit (0);
}

  • 编译 calculator_server.c 和 calculator_client.c

由于rpcgen编译时已经创建了Makefile文件,故可直接执行:make -f Makefile.calculator

  • 将可执行文件 calculator_server 放在主机A,可执行文件 calculator_client 拷贝至主机B

在主机A上运行 calculator_server ,然后在主机B上运行** calculator_client**

三、参考引用

Linux下C实现RPC