1

我正在尝试使用 Sun-RPC 实现多个客户端和多个服务器。但是,我一开始就无法同时运行多个服务器。

这是 IDL

const MAXLEN = 1024;

typedef string filename<MAXLEN>;

typedef int vtimestamp[5];

typedef int sender_id;

typedef int recv_id;

struct request {
    filename name;
    int start;
    vtimestamp ts;
    sender_id sid;
    recv_id rid;
};

typedef struct request request;

typedef opaque filepart[MAXLEN];

struct partreceive {
    filepart data;
    int bytes;
    vtimestamp ts;
    sender_id sid;
    recv_id rid;
};


typedef struct partreceive partreceive;

struct partsend {
    filename name;
    filepart data;
    int bytes;
    vtimestamp ts;
    sender_id sid;
    recv_id rid;
};

typedef struct partsend partsend;

union readfile_res switch (int errno) {
    case 0:
        partreceive part;
    default:
        void;
};

program FTPROG {
    version FTVER {
        readfile_res retrieve_file(request *) = 1;
        int send_file(partsend *) = 2;
    } = 1;
} = 0x31240000;

这是服务器 1 的代码:

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

extern __thread int errno;

int Id = 1;
char fileLog[50] = "server_1_file_log.txt";
int cur_ts[5] = {0};

readfile_res* retrieve_file_1_svc(request *req, struct svc_req *rqstp)
{
    printf("%d",req->rid);
    if(req->rid == Id)
    {
        FILE *file;
        char data[1024];
        int bytes,i;
        static readfile_res res;
        //update the timestamp
        for(i=0;i<5;i++)
            cur_ts[i] = res.readfile_res_u.part.ts[i];
        char fn[3*MAXLEN] = "storage/";
        strcat(fn,req->name);
        file = fopen(fn, "rb");
        if (file == NULL) 
        {
            res.errno = errno;
            return (&res);
        }
        fseek (file, req->start, SEEK_SET);
        bytes = fread(res.readfile_res_u.part.data, 1, 1024, file);
        res.readfile_res_u.part.bytes = bytes;
        res.readfile_res_u.part.sid = Id;
        res.readfile_res_u.part.rid = req->sid;
        res.errno = 0;
        fclose(file);
        //log the transaction
        FILE *log = NULL;
        log = fopen(fileLog, "a");
        fprintf(log,"R,");
        for(i=0;i<5;i++)
            fprintf(log,"%d,",cur_ts[i]);
        fprintf(log,"%d,",req->sid);
        fprintf(log,"%s,",req->name);
        fprintf(log,"%d\n",req->start);
        fclose(log);
        return (&res);  
    }
}

int* send_file_1_svc(partsend *rec, struct svc_req *rqstp)
{
    int i;
    printf("%d",rec->rid);
    if(rec->rid == Id)
    {
        FILE *file;
        int write_bytes;
        static int result;
        cur_ts[Id]++;
        //update the timestamp
        for(i=0;i<5;i++)
            cur_ts[i] = rec->ts[i];
        char fn[3*MAXLEN] = "storage/";
        strcat(fn,rec->name);
        file = fopen(fn, "a");
        if (file == NULL) {
            result = errno;
            return &result;
        }
        write_bytes = fwrite(rec->data, 1, rec->bytes, file);
        fclose(file);
        result = 0;
        //log the transaction
        FILE *log = NULL;
        log = fopen(fileLog, "a");
        fprintf(log,"S,");
        for(i=0;i<5;i++)
            fprintf(log,"%d,",cur_ts[i]);
        fprintf(log,"%d,",rec->sid);
        fprintf(log,"%s\n",rec->name);
        fclose(log);
        return &result;
    }
}

这是服务器 2:

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

extern __thread int errno;

int Id = 2;
char fileLog[50] = "server_2_file_log.txt";
int cur_ts[5] = {0};

readfile_res* retrieve_file_1_svc(request *req, struct svc_req *rqstp)
{
    printf("%d",req->rid);
    if(req->rid == Id)
    {
        FILE *file;
        char data[1024];
        int bytes,i;
        static readfile_res res;
        //update the timestamp
        for(i=0;i<5;i++)
            cur_ts[i] = res.readfile_res_u.part.ts[i];
        char fn[3*MAXLEN] = "storage/";
        strcat(fn,req->name);
        file = fopen(fn, "rb");
        if (file == NULL) 
        {
            res.errno = errno;
            return (&res);
        }
        fseek (file, req->start, SEEK_SET);
        bytes = fread(res.readfile_res_u.part.data, 1, 1024, file);
        res.readfile_res_u.part.bytes = bytes;
        res.readfile_res_u.part.sid = Id;
        res.readfile_res_u.part.rid = req->sid;
        res.errno = 0;
        fclose(file);
        //log the transaction
        FILE *log = NULL;
        log = fopen(fileLog, "a");
        fprintf(log,"R,");
        for(i=0;i<5;i++)
            fprintf(log,"%d,",cur_ts[i]);
        fprintf(log,"%d,",req->sid);
        fprintf(log,"%s,",req->name);
        fprintf(log,"%d\n",req->start);
        fclose(log);
        return (&res);  
    }
}

int* send_file_1_svc(partsend *rec, struct svc_req *rqstp)
{
    int i;
    printf("%d",rec->rid);
    if(rec->rid == Id)
    {
        FILE *file;
        int write_bytes;
        static int result;
        cur_ts[Id]++;
        //update the timestamp
        for(i=0;i<5;i++)
            cur_ts[i] = rec->ts[i];
        char fn[3*MAXLEN] = "storage/";
        strcat(fn,rec->name);
        file = fopen(fn, "a");
        if (file == NULL) {
            result = errno;
            return &result;
        }
        write_bytes = fwrite(rec->data, 1, rec->bytes, file);
        fclose(file);
        result = 0;
        //log the transaction
        FILE *log = NULL;
        log = fopen(fileLog, "a");
        fprintf(log,"S,");
        for(i=0;i<5;i++)
            fprintf(log,"%d,",cur_ts[i]);
        fprintf(log,"%d,",rec->sid);
        fprintf(log,"%s\n",rec->name);
        fclose(log);
        return &result;
    }
}

这是我的客户 1 代码。

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

extern __thread int errno;

int Id = 4;
char fileLog[50] = "client_1_file_log.txt";
int cur_ts[5] = {0};
//Explicit Replication due to lack of Active Directory Service in NFS.
int idMap[4] = {0,2,3,1};
char hostMap[4][MAXLEN] = {"","localhost","localhost","localhost"};

int get_file(char *host, char *name, int serverno) //just to ensure all servers are not operating on same domain, we use serverno.
{
    CLIENT *clnt;
    int total_bytes = 0, write_bytes;
    readfile_res *result;
    request req;
    FILE *file;
    req.name = name;
    req.start = 0;
    int i;
    req.sid = Id;
    req.rid = serverno; 
    clnt = clnt_create(host, FTPROG, FTVER, "tcp");
    if (clnt == NULL) 
    {
         clnt_pcreateerror(host);
         exit(1);
    }
    file = fopen(name, "wb");

    FILE *log = NULL;
    log = fopen(fileLog, "a");
    while (1) 
    {
        cur_ts[Id]++;
        for(i=0;i<5;i++)
            req.ts[i] = cur_ts[i];
        req.start = total_bytes;
        result = retrieve_file_1(&req, clnt);

        if (result == NULL) 
        {
            clnt_perror(clnt, host);
            exit(1);
        }
        if (result->errno != 0) 
        {
            errno = result->errno;
            perror(name);
            exit(1);
        }
        write_bytes = fwrite(result->readfile_res_u.part.data, 1, result->readfile_res_u.part.bytes, file);
        total_bytes += result->readfile_res_u.part.bytes;

        //log the transaction
        fprintf(log,"G,");
        for(i=0;i<5;i++)
            fprintf(log,"%d,",cur_ts[i]);
        fprintf(log,"%d,",req.sid);
        fprintf(log,"%s,",req.name);
        fprintf(log,"%d\n",req.start);
        if (result->readfile_res_u.part.bytes < MAXLEN) 
            break;
    }
    fclose(file);       
    fclose(log);
    return 0;
}

int put_file(char *host, char *name, int serverno)//just to ensure all servers are not operating on same domain, we use serverno.
{
    CLIENT *clnt;
    char data[1024];
    int total_bytes = 0, read_bytes;
    int *result;
    partsend part;
    FILE *file;
    int i;
    part.sid = Id;
    part.rid = serverno;
    clnt = clnt_create(host, FTPROG, FTVER, "tcp");
    if (clnt == NULL) 
    {
         clnt_pcreateerror(host);
         exit(1);
    }
    file = fopen(name, "r");
    part.name = name;
    FILE *log = NULL;
    log = fopen(fileLog, "a");
    for(i=0;i<5;i++)
        part.ts[i] = cur_ts[i];
    while (1) 
    {
        part.bytes = total_bytes;

        read_bytes = fread(part.data, 1, MAXLEN, file);
        total_bytes += read_bytes;
        part.bytes = read_bytes;
        result = send_file_1(&part, clnt);
        if (result == NULL) 
        {
            clnt_perror(clnt, host);
            exit(1);
        }
        if (*result != 0) 
        {
            errno = *result;
            perror(name);
            exit(1);
        }
        for(i=0;i<5;i++)
            cur_ts[i] = part.ts[i];
        //log the transaction
        fprintf(log,"P,");
        for(i=0;i<5;i++)
            fprintf(log,"%d,",cur_ts[i]);
        fprintf(log,"%d,",part.sid);
        fprintf(log,"%s,",part.name);
        fprintf(log,"%d\n",part.bytes);
        if (read_bytes < MAXLEN) 
            break;
    }
    fclose(file);
    fclose(log);
    return 0;
}

int read_command(char *host)
{
    char command[MAXLEN], filepath[MAXLEN];
    int serverno;
    printf("> ");
    fflush(stdin);
    scanf("%s",command);
    if(strcmp(command, "exit") == 0)
    {
        exit(0);
    }
    scanf(" %s %d",filepath,&serverno);
    if(serverno<=0 || serverno>=4)
    {
        printf("Choose a server number in [1,2,3].");
    }
    else
    {
        if (strcmp(command, "get") == 0) 
        {
            return get_file(host,filepath,serverno);
        } 
        else if(strcmp(command, "put") == 0)
        {
            int updateResult,replicationResult=-1;
            updateResult = put_file(host,filepath,serverno);
            /*if(updateResult == 0)
            {
                //explicit Replication
                replicationResult = put_file(hostMap[serverno],filepath,idMap[serverno]);
            }
            else if(replicationResult != 0)
            {
                printf("Replication failed.");
            }*/
            return 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;
}

我正在尝试使用 Maekawa 算法通过我的客户端显式实现文件复制。然而,在同一个本地主机上的 RPC 上运行多个服务器是非常不可能的。甚至可能吗?如果我在不同的计算机上运行代码,那会起作用吗?目前,我从在第一台服务器之后运行的服务器收到分段错误。客户端只是脱口而出 Connection reset by peer。无论如何我可以完成这项工作吗?

4

0 回答 0