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

时间:2014-03-04 03:07:41

标签: 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;
}

我需要呼叫方和发送方都可以自由接收和发送消息。

1 个答案:

答案 0 :(得分:1)

您获得的errno表示您将无效参数传递给msgsnd。根据{{​​3}}:

  

[EINVAL]       msqid的值不是有效的消息队列标识符,或者mtype的值小于1;或者msgsz的值小于0或大于系统强加的限制。   块引用

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

编辑:Mike Wilkins发现了它。他的评论:

  

mtype可能是问题(不是msqid)。 mtype需要> 0.代码   在OP中专门将其设置为0