Sun RPC:传输二进制文件

Sun RPC:传输二进制文件,c,ftp,rpc,sunrpc,C,Ftp,Rpc,Sunrpc,我想将二进制文件传输到远程服务器。我的代码使用SUN/oncpc(Linux上的rpcgen)。我使用的是C语言。我已经为服务器和客户端编写了代码,它可以用于文本文件,但当我尝试传输二进制文件时,它会说文件在传输后已损坏。我将数据块存储在字符数组或XDR字符串中。我认为将数据存储为字符数组存在一些问题。谁能告诉我是什么问题吗?谁能帮帮我吗 如果有人想看看我在做什么,我将把我的代码片段附加在这里以供参考 我的IDL: const MAXLEN = 1024; /* * Type for sto

我想将二进制文件传输到远程服务器。我的代码使用SUN/oncpc(Linux上的rpcgen)。我使用的是C语言。我已经为服务器和客户端编写了代码,它可以用于文本文件,但当我尝试传输二进制文件时,它会说文件在传输后已损坏。我将数据块存储在字符数组或XDR字符串中。我认为将数据存储为字符数组存在一些问题。谁能告诉我是什么问题吗?谁能帮帮我吗

如果有人想看看我在做什么,我将把我的代码片段附加在这里以供参考

我的IDL:

const MAXLEN = 1024;

/*
 * Type for storing path
 */
typedef string filename<MAXLEN>;

/*
 * Structure for sending request. Expects the path of the file
 * and the byte number at which to start reading the file from
 */
struct request {
    filename name;
    int start;
};

/*
 * Type that represents the structute for request
 */
typedef struct request request;

/*
 * Type for storing a chunk of the file that is being
 * sent from the server to the client in the current
 * remote procedure call
 */
typedef string filechunk<MAXLEN>;

/*
 * Response sent by the server to the client as a response
 * to remote procedure call, containing the filechunk for
 * the current call and number of bytes actually read
 */
struct chunkreceive {
    filechunk data;
    int bytes;
};

/*
 * Type that represents the structure for file's chunks
 * to be received from the server
 */
typedef struct chunkreceive chunkreceive;

/*
 * File data sent by the server from client to store
 * it on the server along with the filename and the
 * number of bytes in the data
 */
struct chunksend {
    filename name;
    filechunk data;
    int bytes;
};

/*
 * Type that represents the structure for file's chunks
 * to be sent to the server 
 */
typedef struct chunksend chunksend;

/*
 * union for returning from remote procedure call, returns
 * the proper chunkdata response if everything worked fine
 * or will return the error number if an error occured
 */
union readfile_res switch (int errno) {
    case 0:
        chunkreceive chunk;
    default:
        void;
};

/*
 * Remote procedure defined in the Interface Definition Language
 * of SUN RPC, contains PROGRAM and VERSION name definitions and
 * the remote procedure signature
 */
program FTPPROG {
    version FTPVER {
        readfile_res retrieve_file(request *) = 1;
        int send_file(chunksend *) = 2;
    } = 1;
} = 0x20000011;
const MAXLEN=1024;
/*
*用于存储路径的类型
*/
typedef字符串文件名;
/*
*用于发送请求的结构。需要文件的路径
*以及从中开始读取文件的字节数
*/
结构请求{
文件名;
int启动;
};
/*
*表示请求的结构的类型
*/
typedef结构请求;
/*
*用于存储正在处理的文件块的类型
*从服务器发送到当前服务器中的客户端
*远程过程调用
*/
typedef字符串文件块;
/*
*服务器作为响应发送到客户端的响应
*到远程过程调用,其中包含
*当前调用和实际读取的字节数
*/
结构块接收{
文件块数据;
整数字节;
};
/*
*表示文件块结构的类型
*要从服务器接收的
*/
typedef结构chunkreceive chunkreceive;
/*
*服务器从客户端发送到存储区的文件数据
*它与文件名和
*数据中的字节数
*/
结构块发送{
文件名;
文件块数据;
整数字节;
};
/*
*表示文件块结构的类型
*要发送到服务器
*/
typedef结构chunksend chunksend;
/*
*用于从远程过程调用返回的联合,返回
*如果一切正常,正确的数据响应
*或在发生错误时返回错误号
*/
union readfile_res开关(int errno){
案例0:
分块接收分块;
违约:
无效的
};
/*
*用接口定义语言定义的远程过程
*包含程序和版本名定义以及
*远程过程签名
*/
程序FTPPROG{
版本FTPVER{
readfile\u res retrieve\u file(请求*)=1;
int send_文件(chunksend*)=2;
} = 1;
}=0x2000011;
我的服务器:

#include <rpc/rpc.h>
#include <stdio.h>
#include "ftp.h"

extern __thread int errno;

readfile_res* retrieve_file_1_svc(request *req, struct svc_req *rqstp)
{
    FILE *file;
    char data[1024];
    int bytes;
    static readfile_res res;

    file = fopen(req->name, "rb");
    if (file == NULL) {
        res.errno = errno;
        return (&res);
    }

    fseek (file, req->start, SEEK_SET);
    bytes = fread(data, 1, 1024, file);

    res.readfile_res_u.chunk.data = data;
    res.readfile_res_u.chunk.bytes = bytes;

    /*
     * Return the result
     */
    res.errno = 0;
    fclose(file);
    return (&res);
}

int* send_file_1_svc(chunksend *rec, struct svc_req *rqstp)
{
    FILE *file;
    int write_bytes;
    static int result;

    file = fopen(rec->name, "a");
    if (file == NULL) {
        result = errno;
        return &result;
    }

    write_bytes = fwrite(rec->data, 1, rec->bytes, file);
    fclose(file);

    result = 0;
    return &result;
}
#包括
#包括
#包括“ftp.h”
外部线程内部错误号;
readfile\U res*检索\U file\U 1\U svc(请求*req,结构svc\U req*rqstp)
{
文件*文件;
字符数据[1024];
整数字节;
静态读取文件;
文件=fopen(请求->名称,“rb”);
if(file==NULL){
res.errno=errno;
返回(&res);
}
fseek(文件,请求->开始,搜索设置);
字节=fread(数据,1024,文件);
res.readfile_res_.chunk.data=数据;
res.readfile_res_.chunk.bytes=字节;
/*
*返回结果
*/
res.errno=0;
fclose(文件);
返回(&res);
}
int*send\u file\u 1\u svc(chunksend*rec,struct svc\u req*rqstp)
{
文件*文件;
int写入字节;
静态int结果;
file=fopen(rec->name,“a”);
if(file==NULL){
结果=错误号;
返回和结果;
}
write_bytes=fwrite(记录->数据,1,记录->字节,文件);
fclose(文件);
结果=0;
返回和结果;
}
我的客户:

#include <rpc/rpc.h>
#include <stdio.h>
#include <string.h>
#include "ftp.h"

extern __thread int errno;

int get_file(char *host, char *name)
{
    CLIENT *clnt;
    int total_bytes = 0, write_bytes;
    readfile_res *result;
    request req;
    FILE *file;

    req.name = name;
    req.start = 0;

    /*
     * Create client handle used for calling FTPPROG on
     * the server designated on the command line. Use
     * the tcp protocol when contacting the server.
     */
    clnt = clnt_create(host, FTPPROG, FTPVER, "tcp");
    if (clnt == NULL) {
        /*
         * Couldn't establish connection with server.
         * Print error message and stop.
         */
         clnt_pcreateerror(host);
         exit(1);
    }

    file = fopen(name, "wb");

    /*
     * Call the remote procedure readdir on the server
     */
    while (1) {
        req.start = total_bytes;
        result = retrieve_file_1(&req, clnt);
        if (result == NULL) {
            /*
             * An RPC error occurred while calling the server.
             * Print error message and stop.
             */
            clnt_perror(clnt, host);
            exit(1);
        }

        /*
         * Okay, we successfully called the remote procedure.
         */
        if (result->errno != 0) {
            /*
             * A remote system error occurred.
             * Print error message and stop.
             */
            errno = result->errno;
            perror(name);
            exit(1);
        }

        /*
         * Successfully got a chunk of the file.
         * Write into our local file.
         */
        write_bytes = fwrite(result->readfile_res_u.chunk.data, 1, result->readfile_res_u.chunk.bytes, file);
        total_bytes += result->readfile_res_u.chunk.bytes;
        if (result->readfile_res_u.chunk.bytes < MAXLEN) 
            break;
    }

    fclose(file);

    return 0;
}

int put_file(char *host, char *name)
{
    CLIENT *clnt;
    char data[1024];
    int total_bytes = 0, read_bytes;
    int *result;
    chunksend chunk;
    FILE *file;

    /*
     * Create client handle used for calling FTPPROG on
     * the server designated on the command line. Use
     * the tcp protocol when contacting the server.
     */
    clnt = clnt_create(host, FTPPROG, FTPVER, "tcp");
    if (clnt == NULL) {
        /*
         * Couldn't establish connection with server.
         * Print error message and stop.
         */
         clnt_pcreateerror(host);
         exit(1);
    }

    file = fopen(name, "r");

    chunk.name = name;

    /*
     * Call the remote procedure readdir on the server
     */
    while (1) {
        read_bytes = fread(data, 1, MAXLEN, file);
        total_bytes += read_bytes;

        chunk.data = data;
        chunk.bytes = read_bytes;
        result = send_file_1(&chunk, clnt);

        if (result == NULL) {
            /*
             * An RPC error occurred while calling the server.
             * Print error message and stop.
             */
            clnt_perror(clnt, host);
            exit(1);
        }

        /*
         * Okay, we successfully called the remote procedure.
         */
        if (*result != 0) {
            /*
             * A remote system error occurred.
             * Print error message and stop.
             */
            errno = *result;
            perror(name);
            exit(1);
        }

        /*
         * Successfully got a chunk of the file.
         * Write into our local file.
         */
        if (read_bytes < MAXLEN) 
            break;
    }

    fclose(file);

    return 0;
}

int read_command(char *host)
{
    char command[MAXLEN], filepath[MAXLEN];

    printf("> ");
    fflush(stdin);
    scanf("%s %s", command, filepath);

    if (strcmp(command, "get") == 0) {
        return get_file(host, filepath);
    } else if(strcmp(command, "put") == 0){
        return put_file(host, filepath);
    } else if(strcmp(command, "exit") == 0){
        exit(0);
    } else {
        return -1;
    }
}

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

   if (argc != 2) {
        fprintf(stderr, "usage: %s host\n", argv[0]);
        exit(1);
   }

   while(TRUE) {
       result = read_command(argv[1]);
   }

   return 0;
}
#包括
#包括
#包括
#包括“ftp.h”
外部线程内部错误号;
int get_文件(字符*主机,字符*名称)
{
客户*clnt;
int total_bytes=0,write_bytes;
readfile_res*结果;
请求请求;
文件*文件;
req.name=名称;
req.start=0;
/*
*创建用于在上调用FTPPROG的客户端句柄
*在命令行上指定的服务器。使用
*与服务器联系时使用tcp协议。
*/
clnt=clnt_create(主机、FTPPROG、FTPVER、“tcp”);
如果(clnt==NULL){
/*
*无法与服务器建立连接。
*打印错误消息并停止。
*/
clnt_pcreateerror(主机);
出口(1);
}
文件=fopen(名称,“wb”);
/*
*在服务器上调用远程过程readdir
*/
而(1){
req.start=总字节数;
结果=检索文件1(&req,clnt);
如果(结果==NULL){
/*
*调用服务器时发生RPC错误。
*打印错误消息并停止。
*/
clnt_perror(clnt,主机);
出口(1);
}
/*
*好的,我们成功地调用了远程过程。
*/
如果(结果->错误号!=0){
/*
*发生远程系统错误。
*打印错误消息并停止。
*/
errno=结果->errno;
佩罗尔(姓名);
出口(1);
}
/*
*已成功获取文件的一块。
*写入本地文件。
*/
write_bytes=fwrite(结果->readfile_res_.chunk.data,1,结果->readfile_res_.chunk.bytes,文件);
总字节数+=结果->读取文件\u res\u.chunk.bytes;
如果(结果->读取文件\u res\u.chunk.bytes*bytes = fread(data, 1, 1024, file);
res.readfile_res_u.chunk.data = data;*
*bytes = fread(res.readfile_res_u.chunk.data, 1, 1024, file);*