C语言RPC编程:替换RPC_ANYSOCK为固定端口后libtirpc失效问题
问题原因与解决方法
核心原因
libtirpc与原glibc集成的Sun RPC在端口绑定逻辑上存在关键差异:
- 旧版Sun RPC中,将
RPC_ANYSOCK替换为固定端口时,会自动同时绑定TCP和UDP协议的端口 - libtirpc则要求显式指定协议类型,否则默认仅处理UDP协议的socket,导致TCP端口无法正确绑定
另外,部分老旧rpcgen生成的代码仅初始化了UDP服务socket,未对TCP做显式处理,迁移到libtirpc后这个问题被直接暴露。
解决方法
1. 显式指定TCP协议创建RPC服务socket
修改代码中创建RPC服务的逻辑,分别为TCP和UDP协议创建socket并绑定固定端口。示例如下:
#include <rpc/rpc.h> #include <netinet/in.h> #include <string.h> #include <stdlib.h> #include <stdio.h> // 替换原单一服务创建逻辑,同时初始化TCP和UDP服务 int main(int argc, char **argv) { SVCXPRT *tcp_transp, *udp_transp; struct sockaddr_in server_addr; extern void rpc_program_1(struct svc_req *, SVCXPRT *); // 初始化TCP服务结构 memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(62222); server_addr.sin_addr.s_addr = INADDR_ANY; // 创建TCP传输通道 tcp_transp = svc_tli_create(RPC_RAWFD, (struct sockaddr *)&server_addr, sizeof(server_addr), IPPROTO_TCP, 0); if (tcp_transp == NULL) { perror("Failed to create TCP RPC transport"); exit(1); } // 注册TCP服务 if (!svc_register(tcp_transp, RPC_PROG, RPC_VERS, rpc_program_1, 0)) { svc_destroy(tcp_transp); perror("Failed to register TCP RPC service"); exit(1); } // 保留UDP服务(若业务需要UDP支持) udp_transp = svc_create(rpc_program_1, RPC_PROG, RPC_VERS, "udp"); if (udp_transp == NULL) { svc_destroy(udp_transp); perror("Failed to create UDP RPC transport"); exit(1); } svc_run(); perror("svc_run failed"); exit(1); }
2. 检查rpcgen生成的服务注册逻辑
如果代码是rpcgen自动生成的,打开.x文件对应的_svc.c文件,确认是否存在TCP协议的注册代码。若没有,手动添加上述TCP服务的创建与注册逻辑。
3. 验证绑定结果
启动服务后,用以下命令检查端口监听状态,确认TCP端口62222处于LISTEN状态:
ss -tulpn | grep 62222
4. 排查libtirpc配置(可选)
如果上述修改仍无效,检查/etc/netconfig文件,确认tcp协议条目存在且配置正确:
tcp tpi_cots_ord inet tcp - -
内容的提问来源于stack exchange,提问作者MichiH
相关产品推荐
相关产品推荐

