构造自定义结构化的消息进行文件传输

每个记录前冠以它的长度

PIPE_BUF可原子地写往一个管道或FIFO的最大数据量

把字节流分隔成各个记录由应用程序来实现

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/wait.h>

#define MAXMESGDATA (PIPE_BUF-2*sizeof(long))
#define MESGHDRSIZE (sizeof(struct mymesg)-MAXMESGDATA)

struct mymesg {
	long mesg_len;
	long mesg_type;
	char mesg_data[MAXMESGDATA];
};

ssize_t mesg_send(int fd, struct mymesg *mptr) {
	return write(fd, mptr, MESGHDRSIZE+mptr->mesg_len);
}

ssize_t mesg_recv(int fd, struct mymesg *mptr) {
	size_t len;
	ssize_t n;

	if((n=read(fd, mptr, MESGHDRSIZE))==-1) {
		fprintf(stderr, "read error.\n");
		exit(-1);
	} else if(n==0) {
		return 0;
	} else if(n!=MESGHDRSIZE) {
		fprintf(stderr, "message header: expected %d, got %d\n", MESGHDRSIZE, n);
		exit(-1);
	}

	if((len=mptr->mesg_len)>0) {
		if((n=read(fd, mptr->mesg_data, len))!=len) {
			fprintf(stderr, "message data: expected %d, got %d,\n", len, n);
			exit(-1);
		}
	}
	return len;
}

void client(int readfd, int writefd) {
	size_t len;
	ssize_t n;
	struct mymesg mesg;

	if(fgets(mesg.mesg_data, MAXMESGDATA, stdin)==NULL) {
		fprintf(stderr, "fgets error.\n");
		exit(-1);
	}
	len=strlen(mesg.mesg_data);
	if(mesg.mesg_data[len-1]=='\n')
		len--;
	mesg.mesg_len=len;
	mesg.mesg_type=1;

	mesg_send(writefd, &mesg);	

	while((n=mesg_recv(readfd, &mesg))>0) {
		write(STDOUT_FILENO, mesg.mesg_data, n);
	}
}

void server(int readfd, int writefd) {
	FILE *fp;
	ssize_t n;
	struct mymesg mesg;

	mesg.mesg_type=1;
	if((n=mesg_recv(readfd, &mesg))==0) {
		fprintf(stderr, "pathname missing.\n");
		exit(-1);
	}
	mesg.mesg_data[n]='\0';

	if((fp=fopen(mesg.mesg_data, "r"))==NULL) {
		snprintf(mesg.mesg_data+n, sizeof(mesg.mesg_data)-n, ": cannot open, %s\n", strerror(errno));
		mesg.mesg_len=strlen(mesg.mesg_data);
		mesg_send(writefd, &mesg);
	} else {
		while(fgets(mesg.mesg_data, MAXMESGDATA, fp)!=NULL) {
			mesg.mesg_len=strlen(mesg.mesg_data);
			mesg_send(writefd, &mesg);
		}
		fclose(fp);
	}

	mesg.mesg_len=0;
	mesg_send(writefd, &mesg);
}
 
int main(int argc, char *argv[]) {
    int pipe1[2],pipe2[2];
    pid_t childpid;
 
    if(pipe(pipe1) < 0) {
        perror("pipe1 error.\n");
        exit(-1);
    }
 
    if(pipe(pipe2) < 0) {
        perror("pipe2 error.\n");
        exit(-1);
    }
 
    if((childpid=fork()) < 0) {
        perror("fork error");
        exit(-1);
    }
    else if(childpid == 0) {
        if(close(pipe1[1]) == -1) {
            perror("close pipe1 error");
            exit(-1);
        }
        if(close(pipe2[0]) == -1) {
            perror("close pipe2 error");
            exit(-1);
        }
 
        server(pipe1[0], pipe2[1]);
        exit(0);
    }
 
    if(close(pipe1[0]) == -1) {
        perror("parent close pipe1 error");
        exit(-1);
    }
 
    if(close(pipe2[1]) == -1) {
        perror("parent close pipe2 error");
        exit(-1);
    }
 
    client(pipe2[0], pipe1[1]);
 
    if((waitpid(childpid, NULL, 0)) == -1) {
        perror("waitpid error");
        exit(-1);
    }
 
    exit(0);
}

 

posted @ 2022-10-09 09:42  东宫得臣  阅读(16)  评论(0编辑  收藏  举报