如何从一个文件获取消息和消息 ID 到另一个文件?

Posted

技术标签:

【中文标题】如何从一个文件获取消息和消息 ID 到另一个文件?【英文标题】:How to get message and message id from one file to another file? 【发布时间】:2015-05-25 11:37:16 【问题描述】:

在从 send.c 发送消息和进程 id 后,如何从 get.c 文件中的消息队列中获取消息?

来自 send.c:

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

 #define   MAX_COUNT  200
 #define   BUF_SIZE   100
 #define MSGSZ     255
 #define KEY 10
  //from http://www.tldp.org/LDP/LG/issue89/misc/raghu/send.c.txt
  /*
   * Declare the message structure.
   */
    typedef struct msgbuf 
     long    mtype;
     char    mtext[MSGSZ + 1];
      message_buf; 

     static message_buf sbuf;
      static size_t buf_length;
     static int mqid;  

      int main(int argc, char*argv[])
      
      pid_t  pid;
      int    i;
      char   buf[BUF_SIZE];

    if ((pid = getpid()) < 0)  //getting child process id
     perror("unable to get pid \n");
      
      else 
    printf("The process id is %d \n", pid);
    

       char line[256];
      int c = 0;  //for character count 

     printf("enter word/s (must be less than or equal 256 characters): \n");
     fgets(line, 256, stdin);

     printf("\n");
     if ( c > 256 )
     
     printf("Must enter less than or equal to 256 characters.");
     printf("Has %d characters", countChar(line)); 
      exit(0);
      

      (void) strcpy(sbuf.mtext, line);
       buf_length = strlen(sbuf.mtext) + 1;

        sbuf.mtype = pid; 
        logMessage(sbuf.mtype, line);     
     

     int countChar(char *s) 
      
     int len = 0; 
     for(; *s != '\0'; s++, len++); 
       return len; 
      

     int logMessage(int serviceId,char*message)
    
    int rv, mask, msgid;  
    key_t key = KEY;
    mask = 0644|IPC_CREAT;
    msgid = msgget(key, mask);

if (msgsnd(msgid, &sbuf, buf_length, IPC_NOWAIT) < 0) //sending message

 perror("msgsnd");
 exit(1);
 
 else
 
 printf("id - %d : message - %s \n", serviceId, message);
 

return rv;
  

来自get.c:

  #include <stdio.h>
  #include <stdlib.h>
  #include <signal.h>
  #include <sys/msg.h>
  #include <sys/ipc.h> 
  #include <stdarg.h>
  #include <sys/types.h>
  #include <unistd.h>
  #include <errno.h>
  #include <string.h>
  #define MSGSZ    255
  #define MSGCHARS     255
  #define KEY 10

 typedef struct msgbuf
 
int mtype;
char mtext[MSGSZ]; 
message_buf;

static int queue_id;
void     INThandler(int);

 int main(int argc, char*argv[])

 key_t key = KEY
message_buf  rbuf;
 int msgflg = 0644;
int msqid = msgget(key, msgflg);

if (msqid < 0) 
    perror("msgget");
    exit(1);
    
  rbuf.mtype = 1;
  for(;;)
 if (msgrcv(msqid, &rbuf, MSGSZ, 1, 0) < 0) 
    perror("msgrcv");
    exit(1);
   
   printf("id - %d : message - %s ", rbuf.mtype, rbuf.mtext);
    

     signal(SIGINT, INThandler);//the function starts with ctrl+c. 
     while (1)
      pause();

return 0;


  void  INThandler(int sig)//this function  deletes the message queue
  
 signal(sig, SIG_IGN);
 int mask, msgid;
 key_t key = KEY;
mask = 0644;
msgid = msgget(key, mask);  

if (msgid == -1) 
    printf("Message queue does not exist.\n");
    exit(EXIT_SUCCESS);


if (msgctl(msgid, IPC_RMID, NULL) == -1) 
    fprintf(stderr, "Message queue could not be deleted.\n");
    exit(EXIT_FAILURE);

    else 
printf("Message queue was deleted.\n");
    
    exit(0);
return EXIT_SUCCESS;  

我能够从 send.c 成功发送进程 ID 和消息,但是在执行 get.c 时,代码什么也没有返回。你如何解决这个问题?

【问题讨论】:

如果你能更好地缩进你的代码会很有帮助。 你的意思是get.c和send.c需要整理一下吗?还是其中之一? 你应该在问之前做。您想节省一些时间,但是,您会花费更多时间,因为没有人愿意阅读您的代码,也不想提供答案。 我刚刚修复了代码中的基本错误,但我希望 get.c 返回一些打印的东西,而不是什么。 【参考方案1】:

msgrcv() 的 POSIX 规范确定了您的问题。 msgtyp 参数是第四个参数,在您的代码中指定为 1

参数msgtyp指定请求的消息类型如下:

如果msgtyp为0,则应接收队列中的第一条消息。

如果msgtyp大于0,则应接收msgtyp类型的第一条消息。

如果msgtyp小于0,则接收小于等于msgtyp绝对值的最低类型的第一个消息。

由于发送进程不是init 进程,所以永远不会有来自 PID = 1 的消息。只需将您的调用更改为:

if (msgrcv(msqid, &rbuf, MSGSZ, 1, 0) < 0)

if (msgrcv(msqid, &rbuf, MSGSZ, 0, 0) < 0)

表示接收器的下一次运行得到:

Waiting...
id - 60464 : message -  Waiting...
id - 60478 : message -  Waiting...
id - 60482 : message -  Waiting...
id - 71796 : message -  Waiting...

Waiting... 是在 if 语句之前的循环内的 printf() 语句中打印的。这表明来自先前中止尝试读取消息的消息正在等待读取。

消息返回为零长度,因为您在定义消息结构时不够小心。特别是,接收消息结构使用int而不是规范要求的long,所以在我的机器上sizeof(int) == 4sizeof(long) == 8的值是little-endian,接收器中的字符串相对错位到发送方中的字符串,并放置 0 个字节。修复它并传输消息。

请注意,中断处理程序设置得不够早;它从未在原始代码中实际使用过。

课程:

    仔细阅读规范。 使用一致的结构定义(创建发送方和接收方都使用的标头)。 正确定位信号处理代码。 阅读How to avoid using printf() in a signal handler。这里会相当安全,但从技术上讲,这是未定义的行为,应该避免。

代码:send.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>

#define MSGSZ   255
#define KEY     10

typedef struct msgbuf

    long mtype;
    char mtext[MSGSZ+1];
 message_buf;

int main(void)

    message_buf sbuf;
    sbuf.mtype = getpid();

    printf("The process id is %ld\n", sbuf.mtype);

    printf("enter word/s (must be less than %d characters):\n", MSGSZ+1);
    if (fgets(sbuf.mtext, sizeof(sbuf.mtext), stdin) == 0)
    
        printf("EOF detected\n");
        exit(EXIT_FAILURE);
    

    printf("\n");

    key_t key = KEY;
    int mask = 0644 | IPC_CREAT;
    int msgid = msgget(key, mask);
    if (msgid < 0)
    
        fprintf(stderr, "Failed to create msg key %d\n", key);
        exit(EXIT_FAILURE);
    

    if (msgsnd(msgid, &sbuf, strlen(sbuf.mtext)+1, IPC_NOWAIT) < 0)
    
        perror("msgsnd");
        exit(EXIT_FAILURE);
    

    printf("id - %ld : message - %s\n", sbuf.mtype, sbuf.mtext);

    return 0;

代码:recv.c

#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>

#define MSGSZ    255
#define KEY 10

typedef struct msgbuf

    long mtype;
    char mtext[MSGSZ+1];
 message_buf;

static void INThandler(int);

int main(void)

    key_t key = KEY;
    int msgflg = 0644;
    message_buf rbuf;

    int msqid = msgget(key, msgflg);

    if (msqid < 0)
    
        perror("msgget");
        exit(1);
    

    signal(SIGINT, INThandler);

    rbuf.mtype = 1;
    for ( ; ; )
    
        printf("Waiting...\n");
        ssize_t nbytes = msgrcv(msqid, &rbuf, MSGSZ, 0, 0);
        if (nbytes < 0)
        
            perror("msgrcv");
            exit(1);
        
        printf("id - %ld : message (%d) - %s", rbuf.mtype, (int)nbytes, rbuf.mtext);
    

    return 0;


static void  INThandler(int sig)

    signal(sig, SIG_IGN);
    int mask, msgid;
    key_t key = KEY;
    mask = 0644;
    msgid = msgget(key, mask);

    if (msgid == -1)
    
        printf("Message queue does not exist.\n");
        exit(EXIT_SUCCESS);
    

    if (msgctl(msgid, IPC_RMID, NULL) == -1)
    
        fprintf(stderr, "Message queue could not be deleted.\n");
        exit(EXIT_FAILURE);
    
    else
        printf("Message queue was deleted.\n");
    exit(0);

样品运行

$ ./send <<< "The message to be sent."
The process id is 71901
enter word/s (must be less than 256 characters):

id - 71901 : message - The message to be sent.

$ ./send <<< "Another message to be sent."
The process id is 71902
enter word/s (must be less than 256 characters):

id - 71902 : message - Another message to be sent.

$ ./send <<< "A third message sent to the receiver."
The process id is 71903
enter word/s (must be less than 256 characters):

id - 71903 : message - A third message sent to the receiver.

$ ./recv
Waiting...
id - 71901 : message (25) - The message to be sent.
Waiting...
id - 71902 : message (29) - Another message to be sent.
Waiting...
id - 71903 : message (39) - A third message sent to the receiver.
Waiting...
^CMessage queue was deleted.
$

【讨论】:

以上是关于如何从一个文件获取消息和消息 ID 到另一个文件?的主要内容,如果未能解决你的问题,请参考以下文章

从一个活动获取变量到另一个活动

如何将有关从通道获取的消息的信息放入 JSON 文件?

试图获取非对象的属性

如何使用用户帐户获取/获取消息 (discord.py)

无法将自定义消息从一个控件发送到另一个控件

如何从 smack 中的消息 ID 获取消息。