1、客户端服务器需求
2、int pipe(int fd[2])//返回两个文件描述符,fd[0]读,fd[1]写;
宏S_ISFIFO用来确定一个文件描述符或者文件是管道还是FIFO;
3、半双工通信管道的使用:
一对父子进程,由父进程创建一个管道,子进程复制副本;父进程关闭读fd[0],子进程关闭写fd[1];实现了单向父 ----> 子的通信
因为父进程创建的管道资源是属于父子进程公共分享的空间,这个资源只在父进程创建了一份;
4、如何理解who | sort | lp ----->
实际上是终端bbsh创建了先创建了2个父进程管道空间和三个进程:
(1)piie()--->exec()
4、如何实现全双工通信
(1)父进程创建两个管道,一个管道用于读,一个用于写
子进程捏住读和写句柄;
父进程也同时捏住读和写;
对于用户态来说,只需要往自己拿着的句柄当作普通文件是使用即可;
比如说父进程客户端-》先发送文件路径过去,write(fd1, pathname, n); 然后等着读文件的内容:read(fd2, buff, n);
同理子进程作为服务器:先接收文件路径:read(fd1, buff_pathname, n); 然后打开这个文件,再把内容发送给客户端write(fd2. buffcontex, n);
int main()
{
int pipe1[2],pipe2[2];;pipe(pipe1);
pipe(pipe2);
childpid = fork();
if(child == 0) // 子进程--->服务器
{
close(pipe1[1]);//关1写---》pipe1[0]用于读
close(pipe2[0]);//关2读---》pipe2[1]用于写server(pipe1[0], pipe2[1]);
exit(0);
}
//父进程---》客户端
close(pipe1[0]);
close(pipe2[1]);
client(pipe1[1], pipe2[0]);//pid_t waitpid(pid_t pid, int *status, int options);
waitpid(childpid, NULL, 0);//
exit(0);
}
//子进程调用exit的时候,将变成僵尸进程,内核会给父进程发送SIGCHILD信号,父进程默认是忽略的,但是此处使用了waitpid取得终止子进程的终止状态;
//如果没有waitpid的话,一旦父进程终止后,这个子进程将变成孤儿进程(托孤给init进程管理),内核将为此向init进程发送另外一个SIGCHLD信号
void client(int readfd, int writefd) //客户端从标准输入获取文件路径, 发送到服务器,然后接收文件内容
{
fgets(buff, MAXLINE, stdin);//fgets会把\n字符也算进去,这样len就等于实际字节数+1(\n)了;
len = strlen(buff);if(buff[len-1] == '\n')//这个是成立的
len=len-1;
write(writefd, buff, len);while( (n = read(readfd, buff, len)) > 0)//给完路径就等着接收数据了
{
printf("%s\n", buff);
}
}
void server(int readfd, int writefd)//服务器先接收客户端发来的文件路径,然后打开文件,把文件内容发送给客户端
{n = read(readfd, buff, MAXLINE);
buff[n] = '\0';//注意不是buff[n-1]fd = open(buff, O_RDONLY);
if(fd < 0)//打开出错了,告诉客户端发过来的路径有问题
{
snprintf(buff + n, sizeof(buff) - n; ":can't open %s\n", strerror(errno));
write(writefd, buff, n);
}
else
{
while((n = read(fd, buff, MAXLINE)) > 0)
{
write(writefd, buff, n);
}
close(fd);
}}
5、Unix网络编程---进程间通信书中提到某些系统通过单管道实现全双工通信,实际上再很多系统上是不支持的
#include<unistd.h>
#include<stdio.h>
int main(void)
{
int fd[2], n;
char c;
pid_t childpid;pipe(fd);
childpid = fork();
if(childpid == 0)
{
sleep(3);
n = read(fd[0], &c, 1);
printf("child read %c\n", c);
write(fd[0], "c", 1);
exit(0);
}
waitpid(childpid, NULL, 0);write(fd[1], "p", 1);
n = read(fd[1], &c, 1);
printf("parents read %c\n", c);return 0;
}
6、标准IO也提供了操作管道的接口(这一块用到的是再学吧,跟用户输入有关)
#include<stdio.h>
FILE * popen (const char* command, const char *type);//其中command是一个
int pclose(FILE* stream);