UNIX网络编程之管道

                                                                                                                        管道

    所有式样的UNIX都提供管道。它由pipe函数创建。提供一个单路(单向)数据流。

   函数原型:
           #include <unistd.h>

           int pipe(int fd[2])

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

   单个进程中的管道:
   

两个不同进程间的通信:

下面给出一个简单的客户端和服务器例子。main函数创建两个管道并用fork生成一个子进程。客户然后作为父进程运行,服务器作为子进程运行,第一个管道用于从客户端向服务器发送路径名,第二个管道用于从服务器向客户端发送该文件的内容。

     其大概的布局如图:

    我们先给出main函数:

#include"uitil.h"

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

    int res1;
    int res2;
    //创建管道
    res1 = pipe(pipe1);
    if(res1 == -1){
        cout << "pipe error." << endl;
        exit(1);
    } 
    
    res2 = pipe(pipe2);
    if(res2 == -1){
        cout << "pipe error." << endl;
        exit(1);
    } 
    //fork用于创建一个子进程
    pid = fork();
    if(pid == 0){
        cout << "child." << endl;
        //child
        //子进程从管道1中读数据,写到管道2中
        close(pipe1[1]);
        close(pipe2[0]);
        
        server(pipe1[0],pipe2[1]);
       
        exit(0);

    }else if(pid > 0){
        cout << "parent." << endl;
        //father
        //父进程从管道2中读数据,写到管道1中
        close(pipe1[0]);
        close(pipe2[1]);
      
        client(pipe2[0],pipe1[1]);
       
        waitpid(pid,NULL,0);
    
        exit(0);
    }else{
        cout << "fork error." << endl;
        exit(1);
    }
    return 0;
}

客户端程序:
void client(int readfd,int writefd)
{
    size_t len;
    ssize_t n;
    char buff[MAXLINE];

    //char *fgets(char*buf,int bufsize,FILE* stream)
    //参数
    //    *buf:字符型指针,指向用来存储所的数据的地址
    //    bufsize:整型数据,指明存储数据的大小
    //    *stream:文件结构体指针,将要读取的文件流
    //返回值:
    //    1.成功,则返回第一个参数buf
    //    2.在读字符时遇到end-of-file,则eof指示器被设置,
    //    如果还没读入任何字符就遇到这种情况,则buf保持原来的内容,返回NULL
    //    3.如果发生读入错误,error指示器被设置,返回NULL,buf的值可能被改变
    
    //stdin代表输入的路径名
    fgets(buff,MAXLINE,stdin);
    len = strlen(buff);
    if(buff[len - 1] == '\n')
        len--;
    //将路径名写入到管道1
    write(writefd,buff,len);

    //客户端从管道2中读取文件的内容
    while((n = read(readfd,buff,MAXLINE)) > 0){
        write(STDOUT_FILENO,buff,n);
    }
    
}

服务器程序:
void server(int readfd,int writefd)
{
    int fd;
    ssize_t n;
    char buff[MAXLINE + 1];

    // ssize_t read(int fd,void* buf,size_t nbytes)
    // 把参数fd所指的文件的nbyte个字节读到buf指针所指的内存,
    // 若nbytes为0,则read()不会有作用并返回0;
    // 返回值为实际读取到的字节数,返回0表示已到达文件尾或无可取的数据,错误返回-1
    // 并将根据不同的错误原因适当的设置错误码
    
    //服务器从管道1中读取路径名
    n = read(readfd,buff,MAXLINE);
    if(n == 0){
        cout << "end_of_file while reading pathname." << endl;
        exit(1);
    }
    buff[n] = '\0';
    //以只读方式打开文件
    fd = open(buff,O_RDONLY);
    if(fd < 0){
        snprintf(buff + n,sizeof(buff) - n,":cant't open ,%s\n",strerror(errno));
        n = strlen(buff);
        write(writefd,buff,n);
    }else{
        //当服务器打开文件成功时,将文件的内容写入到管道2
        while((n = read(fd,buff,MAXLINE)) > 0){
            write(writefd,buff,n);
        }
        //关闭文件
        close(fd);
    }
}

头文件uitil.h:

#pragma once

#include<iostream>
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#define MAXLINE 4096

using namespace std;


执行结果:

打开一个已存在的文件test,服务器将返回文件test的内容

打开一个不存在的文件时,将提示错误!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值