我正在尝试使用 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。无论如何我可以完成这项工作吗?