利用C语言消息队列实现双向通信(非阻塞),终端A手动发消息给终端B,消息 自动接收,终端B也可以手动发消息给终端B,消息自动接收。没有发送和接收消息时 不需要提示用户输入要发送给进程消息
时间: 2024-03-30 15:37:02 浏览: 15
好的,这是一个非常好的问题。我来解答一下。
首先,需要明确一下消息队列的概念。消息队列是一种进程间通信的方式,它可以实现进程之间的数据传递,而不需要像管道、套接字那样需要建立连接。消息队列是一种先进先出的数据结构,它的优点是可以在发送方和接收方之间进行异步通信,即发送方不需要等待接收方的响应,可以直接进行下一步操作。
在C语言中,可以使用系统提供的消息队列函数来实现消息队列的创建、发送和接收等操作。下面是一个简单的例子,实现了两个进程之间的双向通信:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/msg.h>
#define MAX_MSG_SIZE 1024
#define MSG_TYPE_A_TO_B 1
#define MSG_TYPE_B_TO_A 2
struct msgbuf {
long mtype;
char mtext[MAX_MSG_SIZE];
};
int main()
{
int mqid_a_to_b, mqid_b_to_a;
key_t key_a_to_b, key_b_to_a;
struct msgbuf msg;
// 创建消息队列A->B和B->A
key_a_to_b = ftok(".", 'a');
mqid_a_to_b = msgget(key_a_to_b, IPC_CREAT|0666);
if (mqid_a_to_b == -1) {
perror("msgget failed");
exit(1);
}
key_b_to_a = ftok(".", 'b');
mqid_b_to_a = msgget(key_b_to_a, IPC_CREAT|0666);
if (mqid_b_to_a == -1) {
perror("msgget failed");
exit(1);
}
while (1) {
// 接收A发来的消息
if (msgrcv(mqid_a_to_b, &msg, MAX_MSG_SIZE, MSG_TYPE_A_TO_B, IPC_NOWAIT) != -1) {
printf("Received from A: %s\n", msg.mtext);
}
// 接收B发来的消息
if (msgrcv(mqid_b_to_a, &msg, MAX_MSG_SIZE, MSG_TYPE_B_TO_A, IPC_NOWAIT) != -1) {
printf("Received from B: %s\n", msg.mtext);
}
// 发送消息给B
fgets(msg.mtext, MAX_MSG_SIZE, stdin);
if (msg.mtext[0] != '\n') {
msg.mtype = MSG_TYPE_A_TO_B;
msgsnd(mqid_b_to_a, &msg, strlen(msg.mtext)+1, IPC_NOWAIT);
}
// 发送消息给A
if (msgrcv(mqid_a_to_b, &msg, MAX_MSG_SIZE, MSG_TYPE_A_TO_B, IPC_NOWAIT) != -1) {
msg.mtype = MSG_TYPE_B_TO_A;
msgsnd(mqid_a_to_b, &msg, strlen(msg.mtext)+1, IPC_NOWAIT);
}
usleep(100);
}
return 0;
}
```
在上面的代码中,我们创建了两个消息队列A->B和B->A,并使用一个死循环来接收和发送消息。在每次循环中,我们先尝试接收A和B发来的消息,如果有消息就打印出来。然后从终端输入一个消息,如果不是空行就发送给B。接着尝试从A->B的消息队列中接收消息,如果有消息就将其发送给A->B的消息队列。注意,在发送消息时我们使用了`IPC_NOWAIT`标志,表示如果消息队列已满就立即返回,不会阻塞等待。这样可以保证消息的非阻塞发送和接收。
另外,我们还定义了两个消息类型`MSG_TYPE_A_TO_B`和`MSG_TYPE_B_TO_A`,分别表示A->B和B->A的消息。这样可以在发送和接收消息时进行区分。
希望这个例子能够帮助到你,如果有任何问题欢迎继续提问。