RPC:远程过程调用
默认情况下服务器并不多线程化:
rpcgen -C data.x -DDEBUG
gcc server.c data_svc.c data_xdr.c -o server
gcc client.c data_clnt.c data_xdr.c -o client
多线程化:(-M 生成线程安全代码 -A 让服务器根据请求自动创建线程)
rpcgen -C data.x -DDEBUG -M
gcc server.c data_svc.c data_xdr.c -o server
gcc client.c data_clnt.c data_xdr.c -o client
#include <rpc/rpc.h>
char *clnt_sperror(CLIENT *rpch, char *s);
CLIENT *clnt_create(char *host, unsigned long prog, unsigned long vers, char *proto);
void clnt_destroy(CLIENT* cl);//显式终止一个客户的TCP连接
bool_t clnt_control(CLIENT* cl, unsigned int request, char* ptr);//request==CLGET_TIMEOUT/*总超时*/,request==CLGET_RETRY_TIMEOUT/*重试超时(UDP)*/
int svc_dg_enablecache(SVCXPRT* xprt, unsigned long size);//启用UDP高速缓存,使重复的请求不会多次调用过程
#include <rpc/clnt_stat.h>
//RPC_SUCCESS
data.x
struct square_in
{
long arg1;
};
struct square_out
{
long res1;
};
program SQUARE_PROG/*RPC程序*/
{
version SQUARE_VERS
{
square_out SQUAREPROC(square_in) = 1;/*过程*/
}=2;/*版本号*/
}=0x31230000;/*程序号*/
server.c
#include <unistd.h>
#include "data.h"
square_out* squareproc_1_svc(square_in* inp, struct svc_req* rqstp)
{
static square_out out;
printf("arg = %ld\n", inp->arg1);
sleep(5);
out.res1 = inp->arg1 * inp->arg1;
printf("arg = %ld\n", inp->arg1);
return &out;
}
bool_t squareproc_2_svc(square_in* inp, square_out* outp, struct svc_req* rqstp)
{
printf("arg = %ld\n", inp->arg1);
if(rqstp->rq_cred.oa_flavor == AUTH_SYS)
{
struct authunix_parms* au;
au = (struct authunix_parms*)rqstp->rq_clntcred;
printf("AUTH_SYS: host %s, uid %ld, gid %ld\n",
au->aup_machname, (long)au->aup_uid, (long)au->aup_gid);
}
sleep(5);
outp->res1 = inp->arg1 * inp->arg1;
printf("arg = %ld\n", inp->arg1);
return TRUE;
}
int square_prog_2_freeresult(SVCXPRT* transp, xdrproc_t xdr_result, caddr_t result)
{
xdr_free(xdr_result, result);
return 1;
}
client.c
#include "data.h"
int main(int argc, const char* argv[])
{
CLIENT* cl;
square_in in;
square_out out;
struct timeval tv;
if(argc != 3)
{
printf("usage : client <hostname> <integer-value>\n");
exit(-1);
}
cl = clnt_create(argv[1], SQUARE_PROG, SQUARE_VERS, "udp");
auth_destroy(cl->cl_auth);//销毁先前句柄关联的认证,空认证
cl->cl_auth = authunix_create_default();//创建默认的Unix认证结构
tv.tv_sec = 30;
tv.tv_usec = 0;
clnt_control(cl, CLSET_TIMEOUT, (char*)&tv);
clnt_control(cl, CLSET_RETRY_TIMEOUT, (char*)&tv);
if(clnt_control(cl, CLGET_TIMEOUT, (char*)&tv))
printf("timeout = %ld sec, %ld usec\n", tv.tv_sec, tv.tv_usec);
if(clnt_control(cl, CLGET_RETRY_TIMEOUT, (char*)&tv))
printf("retry timeout = %ld sec, %ld usec\n", tv.tv_sec, tv.tv_usec);
in.arg1 = atol(argv[2]);
if(squareproc_2(&in, &out, cl) != RPC_SUCCESS)
{
printf("%s", clnt_sperror(cl, argv[1]));
exit(-1);
}
printf("result : %ld\n", out.res1);
return 0;
}
github: https://github.com/gongluck/unpv22-notes.git