管道通信
目的: 实现 xxz 与 zy 之间的通讯聊天
功能: 同一网络下进行的模拟通讯实现
缺点:没有涉及到网络的通信,只是简单的进程之间模拟的通信
采用到的技术点:
-
1 有名管道
- 优点:
- 在文件系统中作为一个特殊的文件而存在,但管道中的内容却存放在内存中。
- 优点:
-
2 文件操作
-
3 多进程创建与回收
-
4 动态宏定义 【因为是写在一个程序中 模拟两个程序作用】
-
5 文件描述符操作
-
6 系统调用 open write
所需头文件:
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <wait.h>
步骤:
1 创建 两者通信 的管道
-
使用mkfifo函数 作用: 创建有名管道
所需头文件 : #include <sys/types.h> #include <sys/stat.h> 参数: pathname:文件名 mode:文件操作模式,一般用0666(所有用户可读可写) 返回值: 成功:0 失败:-1,一般失败是因为存在与pathname名相同的文件
实现:
// 1.创建xxz给zy发信息的管道
mkfifo("./xxz_to_zy",0666);
// 2.创建zy给xxz发信息的管道
mkfifo("./zy_to_xxz",0666);
2 创建两个进程用来收发消息
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <wait.h>
// 实现 xxz 与 zy之间的通信
int main(int argc, char const *argv[])
{
// 1.创建xxz给zy发信息的管道
mkfifo("./xxz_to_zy", 0666);
// 2.创建zy给xxz发信息的管道
mkfifo("./zy_to_xxz", 0666);
// 3.创建子进程 一个用来发信息 一个用来收信息
int i = 0;
for (i = 0; i < 2; i++)
{
int pid = fork();
if (pid == 0)
{
break;
}
}
if (i == 0)//子进程1 用来发信息
{
}
else if (i == 1)//子进程2 用来收信息
{
}
else if (i == 2)// 当前是父进程 用来回收子进程
{
while (waitpid(-1, NULL, WNOHANG) != -1);
}
return 0;
}
-
3 动态的宏定义谁收谁发
一共两个进程来处理
那发的到底谁来发 用动态宏处理
并且 open函数 属于系统调用 成功返回的是 最小文件描述符
先写发信息:
//子进程1 用来发信息 if (i == 0) { //文件描述符 0标准输入 1标准输出 2标准错误 int fd = 0; //如果有XXZ这个宏,当前用户就是 张优秀 #ifdef XXZ fd = open("./xxz_to_zy", O_RDWR); //此时是张优秀给张十一发消息 此时是只读的 #else fd = open("./zy_to_xxz", O_RDWR); //此时是张十一给张优秀发消息 #endif }
这样就会依据 不同的宏 来决定谁发送的
开始写信息
//开始发信息 while (1) { // 用来存放信息 大小为300字节 char info[300] = {0}; // 从标准输入中获取信息 最多获取300个字节 fgets(info, 300, stdin); //打印展示 printf("我:%s", info); //清除脏数据 也就是按的回车上去的\n info[strlen(info) - 1] = 0; //写进文件 消息 write(fd,info,strlen(info)); //给定结束的条件 使用 比较字符串是否相等 if(strcmp(info,"88") == 0 ) { break; } } close(fd);
完整的发送信息部分:
#include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <wait.h> // 实现 张十一 与 张优秀 之间的通信 int main(int argc, char const *argv[]) { // 1.创建xxz给zy发信息的管道 mkfifo("./xxz_to_zy", 0666); // 2.创建zy给xxz发信息的管道 mkfifo("./zy_to_xxz", 0666); // 3.创建子进程 一个用来发信息 一个用来收信息 int i = 0; for (i = 0; i < 2; i++) { int pid = fork(); if (pid == 0) { break; } } //子进程1 用来发信息 if (i == 0) { //文件描述符 0标准输入 1标准输出 2标准错误 int fd = 0; //如果有XXZ这个宏,当前用户就是 张优秀 #ifdef XXZ fd = open("./xxz_to_zy", O_RDWR); //此时是张优秀给张十一发消息 以可读、可写的方式打开 #else fd = open("./zy_to_xxz", O_RDWR); //此时是张十一给张优秀发消息 #endif //开始发信息 while (1) { // 用来存放信息 大小为300字节 char info[300] = {0}; // 从标准输入中获取信息 最多获取300个字节 fgets(info, 300, stdin); //打印展示 printf("我:%s", info); //清除脏数据 也就是按的回车上去的\n info[strlen(info) - 1] = 0; //写进文件 消息 write(fd,info,strlen(info)); //给定结束的条件 使用 比较字符串是否相等 if(strcmp(info,"88") == 0 ) { break; } } close(fd); } else if (i == 1)//子进程2 用来收信息 { //接收信息 } else if (i == 2)// 当前是父进程 用来回收子进程 { while (waitpid(-1, NULL, WNOHANG) != -1); } return 0; }
动态宏定义写接收信息
else if (i == 1)//子进程2 用来收信息 { int fd = 0; //接收信息 #ifdef XXZ fd = open("./zy_to_xxz",O_RDWR); //读取 张十一发来的信息 #else fd = open("./xxz_to_zy",O_RDWR); //读取 张优秀发来的信息 #endif //开始读取信息 while(1) { // 用来存放信息 大小为300字节 char buf[300] = {0}; read(fd,buf,300); //再定义宏用来决定谁来说话 #ifdef XXZ printf("张优秀说:%s\n",buf); #else printf("张十一说:%s\n",buf); #endif //给定结束的条件 使用 比较字符串是否相等 if(strcmp(buf,"88") == 0 ) { break; } } close(fd); //关闭文件描述符 }
运行效果:
完整代码:
#include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <wait.h> int main(int argc, char const *argv[]) { mkfifo("./xxz_to_zy", 0666); mkfifo("./zy_to_xxz", 0666); int i = 0; for (i = 0; i < 2; i++) { int pid = fork(); if (pid == 0) { break; } } if (i == 0) { int fd = 0; #ifdef XXZ fd = open("./xxz_to_zy", O_RDWR); #else fd = open("./zy_to_xxz", O_RDWR); #endif while (1) { char info[300] = {0}; fgets(info, 300, stdin); printf("我:%s", info); info[strlen(info) - 1] = 0; write(fd, info, strlen(info)); if (strcmp(info, "88") == 0) { break; } } close(fd); } else if (i == 1) { int fd = 0; #ifdef XXZ fd = open("./zy_to_xxz", O_RDWR); #else fd = open("./xxz_to_zy", O_RDWR); #endif while (1) { char info[300] = {0}; read(fd, info, 300); #ifdef XXZ printf("张优秀说:%s\n", info); #else printf("张十一说:%s\n", info); #endif if (strcmp(info, "88") == 0) { break; } } close(fd); } else if (i == 2) { while (waitpid(-1, NULL, WNOHANG) != -1); } return 0; }