A向B发消息,B收到并打印,B向A发消息,A收到并打印,用多进程实现,程序A中父进程向程序B中父进程发消息,程序B中父进程收到消息并打印,程序B中子进程向程序A中子进程发消息,程序A中子进程收到消息并打印;
不同进程间通信用消息队列实现,程序A和程序B创建连接同一个消息队列,程序A中父进程向消息队列中发类型1的消息,程序B中父进程读取消息队列中类型1的消息并打印;程序B中子进程向消息队列中发类型2的消息,程序A中子进程从消息队列中读类型2的消息并打印;
进程退出机制:输入端输入'q'时退出;程序A父进程从终端收到'q'时,阻塞等待程序A子进程退出,并向程序B中父进程发送'q',程序B中父进程收到'q',阻塞等待程序B中子进程退出;程序B中子进程从终端收到'q'时,向程序A中子进程发送'q',并退出进程,程序A中子进程收到'q'时退出。
程序A代码如下
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<string.h>
#include<sys/msg.h>
#include<sys/wait.h>
//定义消息包类型
struct msgbuf
{
long mtype; //消息类型
char mtext[32]; //消息内容
};
int main(int argc, char const *argv[])
{
//创建消息队列
//计算key值
key_t key = ftok("/home/ytc01/HuaQingYuanJian/20230208study/work/",1);
if(-1 == key)
{
perror("ftok");
return -1;
}
//创建消息队列
int msqid = msgget(key,IPC_CREAT | 0664);
if(-1 == msqid){
perror("msgget");
return -1;
}
//创建父子进程
pid_t pid = fork();
if(pid > 0){
//父进程向消息队列中写类型1
struct msgbuf snd;
snd.mtype = 1;
while(1){
bzero(snd.mtext,sizeof(snd.mtext));
//从终端获取消息
printf("A端请输入:");
fgets(snd.mtext,sizeof(snd.mtext),stdin);
snd.mtext[strlen(snd.mtext)-1] = 0;
if(strcasecmp(snd.mtext,"q") == 0){
msgsnd(msqid,&snd,sizeof(snd.mtext),1);
if(-1 == wait(NULL)){
perror("wait");
return -1;
}
break;
}
//向消息队列中发送数据
if(msgsnd(msqid,&snd,sizeof(snd.mtext),1) < 0)
{
perror("msgsnd");
return -1;
}
}
}else if(0 == pid){
struct msgbuf rcv;
//子进程从消息队列中读类型2
while (1)
{
memset(&rcv,0,sizeof(rcv));
//从消息队列中读取数据
//阻塞方式读取,消息队列中第一条消息类型为2的消息
if(msgrcv(msqid,&rcv,sizeof(rcv.mtext),2,0) < 0)
{
perror("msgrcv");
break;
}
if(strcasecmp(rcv.mtext,"q") == 0){
break;
}else{
printf("A reply mtype:%ld mtext=%s\n",rcv.mtype,rcv.mtext);
}
}
}else{
perror("fork");
return -1;
}
return 0;
}
程序B代码如下
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/wait.h>
#include<string.h>
//定义消息包类型
struct msgbuf
{
long mtype; //消息类型
char mtext[32]; //消息内容
};
int main(int argc, char const *argv[])
{
//创建消息队列
//计算key值
key_t key = ftok("/home/ytc01/HuaQingYuanJian/20230208study/work/",1);
if(-1 == key)
{
perror("ftok");
return -1;
}
//创建消息队列
int msqid = msgget(key,IPC_CREAT | 0664);
if(-1 == msqid){
perror("msgget");
return -1;
}
//创建父子进程
pid_t pid = fork();
if(pid > 0){
//父进程从消息队列中读类型1
struct msgbuf rcv;
while (1)
{
memset(&rcv,0,sizeof(rcv));
//从消息队列中读取数据
//阻塞方式读取,消息队列中第一条消息类型为1的消息
if(msgrcv(msqid,&rcv,sizeof(rcv.mtext),1,0) < 0)
// if(msgrcv(msqid,&rcv,sizeof(rcv.mtext),1,IPC_NOWAIT) < 0)
{
perror("msgrcv");
break;
}if(strcasecmp(rcv.mtext,"q") == 0){
if(-1 == wait(NULL)){
perror("wait");
return -1;
}
break;
}else{
printf("B reply mtype:%ld mtext=%s\n",rcv.mtype,rcv.mtext);
}
}
}else if(0 == pid){
//子进程向消息队列中写类型2
struct msgbuf snd;
snd.mtype = 2;
while(1){
bzero(snd.mtext,sizeof(snd.mtext));
//从终端获取消息
printf("B端请输入:");
fgets(snd.mtext,sizeof(snd.mtext),stdin);
snd.mtext[strlen(snd.mtext)-1] = 0;
if(strcasecmp(snd.mtext,"q") == 0){
msgsnd(msqid,&snd,sizeof(snd.mtext),2);
return -1;
//break;
}
//向消息队列中发送数据
if(msgsnd(msqid,&snd,sizeof(snd.mtext),2) < 0)
{
perror("msgsnd");
return -1;
}
}
}else{
perror("fork");
return -1;
}
return 0;
}
效果展示如下图