使用两个管道的客户----服务器模型

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define MAXLINE 4096
#define BUFFSIZE 4096

void client(int, int), server(int, int);

int main(int argc, char *argv[]) {
    int pipe1[2],pipe2[2];
    pid_t childpid;

    if(pipe(pipe1) < 0) {
        perror("pipe1 error");
        exit(-1);
    }

    if(pipe(pipe2) < 0) {
        perror("pipe2 error");
        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);
}

void client(int readfd, int writefd) {
    size_t len;
    ssize_t n;
    char buff[MAXLINE];

    printf("------------starting client------------\n");

    if((fgets(buff, MAXLINE, stdin) == NULL) && ferror(stdin)) {
        perror("fgets error");
        exit(-1);
    }

    printf("client ipc pathname: %s\n", buff);

    len = strlen(buff);
    if(buff[len-1] == '\n')
        len--;

    if(write(writefd, buff, len) != len) {
        perror("write error");
        exit(-1);
    }

    while((n=read(readfd, buff, MAXLINE)) > 0) {
        printf("-----------------print to film----------------\n");
        if (write(STDOUT_FILENO, buff, n) != n ) {
            perror("write error");
            exit(-1);
        }
    }
}

void server(int readfd, int writefd) {
    int fd;
    ssize_t n;
    char buff[MAXLINE+1];

    printf("----------------start server-------------------\n");

    if((n=read(readfd, buff, MAXLINE)) == -1) {
        perror("read error");
        exit(-1);
    }
    if(n == 0) {
        perror("end-of-file while reading pathname");
        exit(-1);
    }
    buff[n]='\0';

    printf("server IPC pathname: %s\n",buff);

    if((fd=open(buff, O_RDONLY)) < 0) {
        snprintf(buff+n, sizeof(buff)-n, ": can't open, %s\n", strerror(errno));
        n=strlen(buff);
        if(write(writefd, buff, n) != n) {
            perror("write error");
            exit(-1);
        }
    }
    else {
        printf("------server open file success-------\n");
        while((n=read(fd, buff, MAXLINE)) > 0) {
            if(write(writefd, buff, n) != n) {
                perror("write error");
                exit(-1);
            }
        }
        close(fd);
    }
}

pipe函数返回两个文件描述符:fd[0]fd[1]。前者打开来读,后者打开来写。

当需要一个双向数据流时,必须创建两个管道,每个方向一个。

1)创建管道1(pipe1[0]pipe1[1])和管道2(pipe2[0]和pipe2[1]);

2)fork

3)父进程关闭管道1的读出端(pipe1[0]);

4)父进程关闭管道2的写入端(pipe2[1]);

5)子进程关闭管道1的写入端(pipe1[1]);

6)子进程关闭管道2的读出端(pipe2[0]);

管道没有名字,因此它们最大的劣势是只能用于有一个共同祖先进程的各个进程之间。

posted @ 2018-01-15 07:58  东宫得臣  阅读(191)  评论(0编辑  收藏  举报