You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

rpcgen生成的C语言RPC程序报错:RPC: Procedure unavailable

RPC客户端报错"RPC: Procedure unavailable"的解决

我在完成作业时遇到问题:需使用RPC协议,通过rpcgen生成程序从远程主机获取时间和日期。编写rpctime.x文件后,执行rpcgen -a rpctime.x生成相关文件,并添加标记为//+的代码行。修改Makefile.rpctime将链接库从-lnsl改为-ltirpc后,执行make -f Makefile.rpctime完成编译。运行./rpctime_server和./rpctime_client 127.0.0.1时,客户端始终报错:

call failed: RPC: Procedure unavailable

但服务端仍在正常运行,请求解决该问题。相关代码如下:

rpctime.x

program RPCTIME
{
    version RPCTIMEVERSION
    {
        long GETTIME() = 1;
    } = 1;
} = 2000001;

rpctime_server.c

#include "rpctime.h"
#include <time.h> //+

long *
gettime_1_svc(void *argp, struct svc_req *rqstp)
{
    static long result;

    time(&result); //+`

    return &result;
}

rpctime_client.c

#include "rpctime.h"
#include "time.h" //+`

void
rpctime_1(char *host)
{
    CLIENT *clnt;
    long *result_1;
    char buf[50];
    char *gettime_1_arg;

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

    result_1 = gettime_1((void*)&gettime_1_arg, clnt);
    if (result_1 == (long *) NULL) {
        clnt_perror (clnt, "call failed"); //此处客户端程序终止
    } else {
        printf("%s\n", ctime_r(result_1, buf)); //+`
    }
#ifndef DEBUG
    clnt_destroy (clnt);
#endif   /* DEBUG */
}


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

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

Makefile.rpctime

# This is a template Makefile generated by rpcgen

# Parameters

CLIENT = rpctime_client
SERVER = rpctime_server

SOURCES_CLNT.c = 
SOURCES_CLNT.h = 
SOURCES_SVC.c = 
SOURCES_SVC.h = 
SOURCES.x = rpctime.x

TARGETS_SVC.c = rpctime_svc.c rpctime_server.c   
TARGETS_CLNT.c = rpctime_clnt.c rpctime_client.c   
TARGETS = rpctime.h   rpctime_clnt.c rpctime_svc.c rpctime_client.c rpctime_server.c

OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o)
OBJECTS_SVC = $(SOURCES_SVC.c:%.c=%.o) $(TARGETS_SVC.c:%.c=%.o)
# Compiler flags 

CFLAGS += -g 
LDLIBS += -ltirpc // 此处原生成-lnsl但无效
RPCGENFLAGS = 

# Targets 

all : $(CLIENT) $(SERVER)

$(TARGETS) : $(SOURCES.x) 
    rpcgen $(RPCGENFLAGS) $(SOURCES.x)

$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) $(TARGETS_CLNT.c) 

$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) $(TARGETS_SVC.c) 

$(CLIENT) : $(OBJECTS_CLNT) 
    $(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) $(LDLIBS) 

$(SERVER) : $(OBJECTS_SVC) 
    $(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)

 clean:
     $(RM) core $(TARGETS) $(OBJECTS_CLNT) $(OBJECTS_SVC) $(CLIENT) $(SERVER)

问题原因与解决方法

1. 客户端参数传递错误

IDL中定义的GETTIME()是无参数过程,但客户端调用时传递了(void*)&gettime_1_arg——一个指向未初始化指针的地址,不符合RPC过程的参数定义。

解决:将客户端调用改为result_1 = gettime_1(NULL, clnt);,传递NULL匹配无参数的过程定义。

2. 服务端函数注册不匹配

rpcgen会根据IDL中的过程名生成调度表,需要确保rpctime_svc.c中的rpctime_1_svc_table调度表正确关联gettime_1_svc函数。如果生成的调度表中没有绑定该函数,服务端无法识别客户端的调用请求。

解决:打开rpctime_svc.c,找到struct svcdisp rpctime_1_svc_table[],确保过程ID为1的条目svc_func指向gettime_1_svc。例如:

struct svcdisp rpctime_1_svc_table[] = {
    { (u_long)1, gettime_1_svc, xdr_void, xdr_long },
    { (u_long)0, NULL, NULL, NULL }
};

3. 代码语法错误

代码中存在几处语法问题,可能导致程序行为异常:

  • rpctime_server.c中time(&result); //+后面的多余反引号需要删除
  • rpctime_client.c中#include "time.h"应改为#include <time.h>(系统头文件用尖括号),同时删除后面的多余反引号

4. RPC服务未正确注册

使用tirpc库时,需确保rpcbind服务正常运行,服务端才能注册RPC服务:

  • 启动rpcbind:sudo systemctl start rpcbind
  • 用rpcinfo -p命令检查是否有程序号2000001的服务注册

5. Makefile依赖问题

当前Makefile会将你修改后的rpctime_client.c和rpctime_server.c列为rpcgen的生成目标,修改rpctime.x后重新make会覆盖你的代码。

解决:修改Makefile中的TARGETS,移除客户端和服务端代码文件:

TARGETS = rpctime.h   rpctime_clnt.c rpctime_svc.c

内容的提问来源于stack exchange,提问作者AlexVs86

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 22:56:29