基于Ubuntu14的Sun XDR RPC图像收发问题求助
我来帮你捋捋Ubuntu 14上用Sun XDR RPC收发图像遇到的这个问题——服务端提示文件空、客户端超时报错,结合你的实现逻辑,大概率是数据在XDR序列化/传输/解析的某个环节掉链子了,咱们一步步排查:
先排查客户端的文件读取与结构体填充问题
- 务必确认文件读取是否完整:很多时候大家会忽略
fread的返回值校验,如果文件路径错误、权限不足或者文件本身损坏,fread实际读取的字节数会小于预期,导致结构体里的图像数据为空。建议加个强校验:FILE *fp = fopen("test.jpg", "rb"); if (!fp) { perror("Failed to open image file"); exit(1); } // 先获取文件大小 fseek(fp, 0, SEEK_END); size_t img_size = ftell(fp); fseek(fp, 0, SEEK_SET); // 分配内存并读取 char *img_data = malloc(img_size); size_t read_size = fread(img_data, 1, img_size, fp); if (read_size != img_size) { fprintf(stderr, "读取图像文件不完整:预期%zu字节,实际读了%zu字节\n", img_size, read_size); free(img_data); fclose(fp); exit(1); } fclose(fp); - 检查
.x文件的结构体定义是否符合XDR规范:图像数据属于可变长度的二进制数据,必须用带长度字段的opaque类型,不然RPCGEN生成的序列化代码会处理失败。正确的定义应该是这样的:
如果你的定义是固定长度数组(比如struct ImageData { unsigned int img_len; // 必须先定义长度字段 opaque img_data<>; // 可变长度的二进制数据 };opaque img_data[1024]),那超过这个长度的图像数据会被截断,服务端自然收到不完整的内容。
检查RPC调用的错误处理
客户端超时报错很大概率是RPC调用本身失败了,你可能没做返回值校验。一定要在调用clnt_call后检查结果,并用clnt_perror打印具体错误,这能快速定位是网络问题、服务端未注册还是参数错误:
// 假设你的RPC程序号是IMAGE_COMPRESS,版本号是1 enum clnt_stat stat = clnt_call(clnt, IMAGE_COMPRESS, (xdrproc_t)xdr_ImageData, &send_struct, (xdrproc_t)xdr_void, NULL, TIMEOUT); if (stat != RPC_SUCCESS) { clnt_perror(clnt, "RPC调用失败"); clnt_destroy(clnt); exit(1); }
比如如果服务端没启动,会打印RPC调用失败: Remote system error;如果程序号/版本号不匹配,会打印RPC调用失败: Program not registered。
服务端的接收与写入校验
- 服务端收到结构体后,第一时间检查
img_len字段是否为0:如果是0,直接说明客户端那边的结构体没正确填充,不用再往下走写入逻辑。 - 写入文件时同样要校验
fwrite的返回值:比如服务端的输出路径有没有写权限?磁盘是否已满?这些都会导致写入失败,但你可能误以为是收到了空数据:FILE *out_fp = fopen("received_img.jpg", "wb"); if (!out_fp) { perror("Failed to open output file"); return; } size_t write_size = fwrite(recv_struct->img_data, 1, recv_struct->img_len, out_fp); if (write_size != recv_struct->img_len) { fprintf(stderr, "写入图像文件不完整:预期%u字节,实际写了%zu字节\n", recv_struct->img_len, write_size); } fclose(out_fp);
额外的调试小技巧
- 用
rpcinfo确认服务端的RPC服务已注册:执行rpcinfo -p localhost,查看你的程序号和版本号是否在列表里,如果没有,说明服务端的svc_register调用失败了。 - 在客户端和服务端分别打印图像的长度和前4个字节的十六进制值:对比两边的输出,就能知道是客户端没发对数据,还是服务端没正确解析。比如客户端打印:
服务端收到后也打印同样的内容,一眼就能定位问题环节。printf("客户端发送:长度%u,前4字节:%02x %02x %02x %02x\n", send_struct.img_len, (unsigned char)send_struct.img_data[0], (unsigned char)send_struct.img_data[1], (unsigned char)send_struct.img_data[2], (unsigned char)send_struct.img_data[3]);
内容的提问来源于stack exchange,提问作者cranberry
相关产品推荐
相关产品推荐

