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

基于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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:28:39