构造自定义结构化的消息进行文件传输
每个记录前冠以它的长度
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); }