linux网络编程_1 管道的创建和使用

管道由pipe函数创建,只能提供单向的数据传送
#include<unistd.h>
int
pipe(int fd[2])
此函数参数fd为两个文件描述符:fd[0],fd[1],一个用来读,一个用来写。
管道是由单个进程创建的,但是只在单个进程内使用的情况很少,一般是用来提供父子进程间的通信的。首先一个进程创建一个管道,然后派生出一个自身的拷贝;
接着,父进程关闭此管道的读出端,而子进程关闭管道的写入端。至此,父子进程之间就建立起了单一方向的数据流的通道。

代码说话
实现父进程通过管道向子进程传送字符串,再通过子进程输出到屏幕
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>

int main()
{
    int        n,fd[2];
    pid_t    pid;
    char    line[1024];//缓冲区
    
    
    if(pipe(fd)<0)//创建管道fd[0]读,fd[1]写
        exit(0);
    if((pid = fork())<0)//创建子进程
        exit(0);
    else if(pid > 0) {//fork函数对父进程和子进程都有返回值,子进程是0,父进程的返回值是子进程的ID(供内核识别)
        close(fd[0]);//关闭管道读出端
        write(fd[1],"I am from parent\n",19);
    }
    else{
        close(fd[1]);
        n = read(fd[0],line,1024);
        write(STDOUT_FILENO,line,n);
    }
    exit(0);

}





/*实现数据双向传送。客户端从标准输入中读入一个目录的路劲名,并把它写入管道。
 *服务器从管道读出路径名,并查看此目录是否存在。如果存在,则读此目录,并将目录下的文件写入另一个管道
 *作为对客户端的回应。如果目录不存在,就写入一条错误信息。客户端随后从管道读出响应并把它写到标准输出
 */
#include    <unistd.h>
#include    <dirent.h>
#include    <limits.h>
#include    <string.h>
#include    <stdio.h>
#include    <stdlib.h>
#include    <errno.h>

#define        bufflen        1024



void err_sys(char *info)                                                        
{                                                                       
    fprintf(stderr, "%s:%s\n",info,strerror(errno));                
        exit(EXIT_FAILURE);                                               
}

void server(int readfd,int writefd){

    ssize_t        n;
    char         buff[bufflen],*ptr;
    struct dirent     *dirp;//
    DIR        *dp;
    
    if((n = read(readfd,buff,bufflen))==0)//因为opendir读目录要读字符串
        exit(0);
    buff[n] ='\0';//字符串的象征
    ptr = buff + n;//ptr指向缓存中的第n个内存单元
    if((dp = opendir(buff)) == NULL)//打开目录
        snprintf(ptr,sizeof(buff)-n,"not find\n");
    else{
        while((dirp = readdir(dp))!=NULL){
            if(strcmp(dirp->d_name,".")==0||strcmp(dirp->d_name,"..")==0)//'.'表示当前目录,'..'表示父目录
                continue;
            strcpy(ptr,dirp->d_name);//将目录名字复制到ptr指向的缓冲区内存单元中,会自动加'\0'
            n = strlen(dirp->d_name);
            ptr+=n;//移动指针
            *ptr=' ';//置空把最后的'\0'去掉,不然后面读取目录的时候遇到'\0'就不会读取了,造成只能读一个目录后面读取不到
            ptr++;//指向下一个单元
        }    
            *ptr='\0';
    }
    n = strlen(buff);
    if((write(writefd,buff,n))!=n)//一次性写到管道1中
        exit(0);
    closedir(dp);
}
/*
 *从标准输入中读入路径名,经管道传送给server,再从另一个管道读出server返回的内容,并将其打印到标准输出
 */
void client(int readfd,int writefd)
{
    char     buff[bufflen];
    int    len;
    size_t n;
    fgets(buff,bufflen,stdin);//读一行,要留一个字符存放'\0'
    len = strlen(buff);//不包括'\0'
    if(buff[len-1] == '\n')
        len--;
    if((write(writefd,buff,len))!=len)//将buff中的内容写入writefd指向的文件中,pipe1[1]
        exit(0);
    while((n = read(readfd,buff,bufflen))>0)//从readfd(pipe2[0])指向的文件中读取bufferlen个字节内容读到buff中
        if((write(STDOUT_FILENO,buff,n))!=n)//STDOUT_FILENO在<unistd.h>
            exit(0);
    printf("\n");
}
/*
程序创建两个双向管道。此后父进程调用client函数,子进程调用server()函数实现数据的双向传递。
子进程调用server向管道中写入数据然后调用exit函数终止退出,然后变成一个僵尸进程(子进程自己终止,父进程仍在运行,且不等待该子进程结束)。
在子进程终止时,内核给父进程发送一个SIGCHLD信号,但此时父进程并没有捕获这个信号,而此信号行为就是忽略。此后不久,父进程的client函数
从子进程传回信息后返回,紧接着就调用waitpid函数来取得已终止子进程的终止状态。要是父进程没有调用waitpid.而是直接终止,那么子进程将会
变成孤儿进程,它的父进程也变成了init进程。

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

    if(pipe(pipe1)<0) //创建管道
        err_sys("pipe1");
    if(pipe(pipe2)<0)
        err_sys("pipe2");
    if((childpid = fork())>0){  //创建子进程,
        close(pipe1[0]);//关闭父进程管道1读
        close(pipe2[1]);//关闭父进程管道2写
            client(pipe2[0],pipe1[1]);
        waitpid(childpid,NULL,0);//取得已终止子进程的终止状态
        exit(0);
    }
    else{//子进程pid=0
        close(pipe1[1]);
        close(pipe2[0]);
        server(pipe1[0],pipe2[1]);
        exit(0);
    }    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值