c - C中使用消息队列的IPC机制

标签 c multithreading unix message-queue

我正在尝试使用 C 中的消息队列实现一种 IPC 机制,用于电话交谈。我创建了两个 .c 文件,一个用于调用者,一个用于接收者。在每个 .c 文件中,我创建了两个线程,一个用于发送消息,另一个用于接收消息。每个线程创建其消息队列。来自调用者的发送消息线程和来自接收者的接收消息线程共享相同的队列,并且彼此相同。

正在创建消息队列,但每当我输入要发送的消息时,它都会失败。 msgsnd(-,-,-,-) 始终返回 -1。

caller.c文件如下:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>

struct msgbuf
{
  long mtype;
  char mtext[50];
}SEND_BUFFER,RECEIVE_BUFFER;

int send_msgQ_id, receive_msgQ_id;
key_t send_key,receive_key;

void * send_message(void * a)
{
send_key = ftok("Caller.c", 'B');
if(send_key==-1)
{
    printf("\n caller send key error");
    exit(1);
}
send_msgQ_id = msgget(send_key, 0666 | IPC_CREAT);
if(send_msgQ_id==-1)
{
    printf("\n caller send msgget error");
    exit(1);
}

printf("\n Enter lines of text, ^D to quit:\n");

    while(fgets(SEND_BUFFER.mtext, sizeof(SEND_BUFFER.mtext), stdin) != NULL)
    {
        SEND_BUFFER.mtype = 0;

        int len = strlen(SEND_BUFFER.mtext);
        if (SEND_BUFFER.mtext[len-1] == '\n')
            SEND_BUFFER.mtext[len-1] = '\0';
        printf("\n Attemping to send %s\n", SEND_BUFFER.mtext);
        if(msgsnd(send_msgQ_id, &SEND_BUFFER, len+1, 0)==-1)
            printf("\n msg sendign error\n");
    }
int i =0;
while(i<9999)
    i++;
msgctl(send_msgQ_id, IPC_RMID, NULL);
return;
}

void * receive_message(void * a)
{
receive_key = ftok("Receiver.c", 'B');
if(receive_key==-1)
{
    printf("\n caller receive key error");
    exit(1);
}
receive_msgQ_id = msgget(receive_key, 0777 | IPC_CREAT);
 if(receive_msgQ_id==-1)
 {
     printf("\n caller receive msgget error");
     exit(1);
 }

printf("\n Ready to receive ");
while(1)
{
   if( msgrcv(receive_msgQ_id, &RECEIVE_BUFFER, sizeof(RECEIVE_BUFFER.mtext), 0, 0)!=-1)
    printf("Received : %s\n", RECEIVE_BUFFER.mtext);
}
return;
}

void initialize()
{

pthread_t send_thread,receive_thread;
pthread_create(&send_thread,NULL,send_message,NULL);
pthread_create(&receive_thread,NULL,receive_message,NULL);
pthread_join(send_thread,NULL);
pthread_join(receive_thread,NULL);
return;
}

int main()
{
printf("\n\n *** Caller Program ***\n");
initialize();
return 0;
}

receiver.c 文件如下(与 caller.c 文件类似):

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>

struct msgbuf
{
long mtype;
char mtext[50];
}SEND_BUFFER,RECEIVE_BUFFER;

int send_msgQ_id, receive_msgQ_id;
key_t send_key,receive_key;

void * send_message(void * a)
{
send_key = ftok("Receiver.c", 'B');
if(send_key==-1)
{
    printf("\n receiver send key error");
    exit(1);
}
send_msgQ_id = msgget(send_key, 0777);
if(send_msgQ_id==-1)
{
    printf("\n receiver msgget error ");
    exit(1);
}
printf("\n Enter lines of text, ^D to quit:\n");

    SEND_BUFFER.mtype = 0;
    while(fgets(SEND_BUFFER.mtext, sizeof(SEND_BUFFER.mtext), stdin) != NULL)
    {
        int len = strlen(SEND_BUFFER.mtext);
        if (SEND_BUFFER.mtext[len-1] == '\n')
            SEND_BUFFER.mtext[len-1] = '\0';
        msgsnd(send_msgQ_id, &SEND_BUFFER, len+1, 0);
    }
    int i =0;
    while(i<9999)
        i++;
msgctl(send_msgQ_id, IPC_RMID, NULL);
return;
}

void * receive_message(void * a)
{
receive_key = ftok("Caller.c", 'B');
if(receive_key==-1)
{
    printf("\n receiver receiver key error");
    exit(1);
}
receive_msgQ_id = msgget(receive_key, 0666);
if(receive_msgQ_id==-1)
{
    printf("\n msgget error");
    exit(1);
}

while(1)
{
    if(msgrcv(receive_msgQ_id, &RECEIVE_BUFFER, sizeof(RECEIVE_BUFFER.mtext), 0, 0)==-1)
        printf("\n msg receiving error");
    else
        printf("Received : %s\n", RECEIVE_BUFFER.mtext);
}
return;
}

void initialize()
{
pthread_t send_thread,receive_thread;
pthread_create(&receive_thread,NULL,receive_message,NULL);
pthread_create(&send_thread,NULL,send_message,NULL);
pthread_join(send_thread,NULL);
pthread_join(receive_thread,NULL);
return;
}

int main()
{
printf("\n\n *** Receiver Program ***\n");
initialize();
return 0;
}

我需要调用者和发送者都可以随意接收和发送消息。

最佳答案

您收到的 errno 表明您向 msgsnd 传递了无效参数。根据man page for msgsnd :

[EINVAL] The value of msqid is not a valid message queue identifier, or the value of mtype is less than 1; or the value of msgsz is less than 0 or greater than the system-imposed limit. Blockquote

我的猜测是 msqid 是有问题的参数。检查调试器中的值或将其打印出来。

编辑:迈克·威尔金斯发现了它。他的评论:

mtype is likely the issue (not msqid). mtype needs to be > 0. The code in the OP specifically sets it to 0

关于c - C中使用消息队列的IPC机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22162061/

相关文章:

c - 简单的输入。程序崩溃

c++ - 移动 strchr 指针后使用 strtok

c - C 中 atoi() 函数的使用

c++ - 以类对象和结构对象 c++ 开始线程

java - 虽然线程中的循环似乎没有运行

windows - 在文件中使用 cygwin 将 windows 路径转换为 ​​unix 路径的命令

c - 在c中逐字读取缓冲区

java - 执行程序终止和关闭之间的区别

c - SIGINT 信号仅被捕获一次

linux - Grep 具有重复字段值的连续行。