C언어 메시지 큐로부터 데이터 수신 함수 msgrcv()

2020. 3. 16. 08:06 컴퓨터/프로그래밍

C함수 메시지 큐로부터 데이터 수신 msgrcv()

메시지 큐로부터 데이터를 수신합니다.

  • 헤더: sys/types.h, sys/ipc.h, sys/msg.h
  • 형태: int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg)
  • 인수: int msqid 메시지 큐 식별자
    void *msgp 전송할 자료
    size_t msgsz 전송할 자료의 크기
    int msgflg 동작 옵션
  • 반환: 0 == 성공, -1 == 실패

msgid는 메시지 큐의 식별자 입니다. msgp는 수신한 데이터로, 구조는 아래와 같습니다.

struct {
   long  data_type;
   char  data_buff[BUFF_SIZE];
}
   또는,
   
struct {
   long  data_type;
   int   data_num;
   char  data_buff[BUFF_SIZE];
}
   또는,
   
struct {
   long  data_type;
   int   data_num;
}

전송 데이터는 long 값을 항상 첫 번째에 가지고 있으며, 이 값을 이용하여 원하는 자료만 걸러 낼 수 있습니다. 그러므로 데이터의 크기에는 long 값이 반드시 들어 가기 때문에 data type을 나타내는 long 크기는 제거합니다.

sizeof( t_data) - sizeof( long)

마지막 int msgflg 는 읽어 들이는 옵션으로 아래와 같은 상수 값을 사용할 수 있으며 OR로 복수 지정할 수 있습니다. 또는 아래의 옵션을 사용하고 싶지 않다면 0 을 사용하면 됩니다.

msgflg 의미
IPC_NOWAIT 메시지 큐에 메시지가 없다면 기다리지 않고 -1 로 복귀합니다.
MSG_NOERROR 메시지 큐에 있는 자료가 준비된 데이터 크기보다 크다면 초과 부분을 잘라 내고 읽어 들일 수 있는 부분만 담아 옮니다. 이 옵션이 없다면 메시지 큐에 자료가 있다고 하더라도 -1로 실패됩니다.

예제

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

#define  BUFF_SIZE   1024

typedef struct {
   long  data_type;
   int   data_num;
   char  data_buff[BUFF_SIZE];
} t_data;

int main( void)
{
   int      msqid;
   t_data   data;

   if ( -1 == ( msqid = msgget( (key_t)1234, IPC_CREAT ¦ 0666))){
      perror( "msgget() 실패");
      exit( 1);
   }
   while( 1 ){
      // 메시지 큐 중에 data_type 이 2 인 자료만 수신
      if ( -1 == msgrcv( msqid, &data, sizeof( t_data) - sizeof( long), 2, 0)){
         perror( "msgrcv() 실패");
         exit( 1);
      }
      printf( "%d - %s\n", data.data_num, data.data_buff);
   }
}

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

#define  BUFF_SIZE   1024

typedef struct {
   long  data_type;
   int   data_num;
   char  data_buff[BUFF_SIZE];
} t_data;

int main( void)
{
   int      msqid;
   int      ndx   = 0;
   t_data   data;

   if ( -1 == ( msqid = msgget( (key_t)1234, IPC_CREAT ¦ 0666))){
      perror( "msgget() 실패");
      exit( 1);
   }

   while( 1 ){
      data.data_type = ( ndx++ % 3) +1;   // data_type 는 1, 2, 3
      data.data_num  = ndx;
      sprintf( data.data_buff, "type=%ld, ndx=%d, http://badayak.com", data.data_type, ndx);

      if ( -1 == msgsnd( msqid, &data, sizeof( t_data) - sizeof( long), 0)){
         perror( "msgsnd() 실패");
         exit( 1);
      }
      sleep( 1);
   }
}
receiver sender
]$ gcc receiver.c -o receiver.out
]$ ./receiver.out
2 - type=2, ndx=2, http://badayak.com
5 - type=2, ndx=5, http://badayak.com
8 - type=2, ndx=8, http://badayak.com
11 - type=2, ndx=11, http://badayak.com
14 - type=2, ndx=14, http://badayak.com

여기서 멈춤이 일어 납니다. 왜냐하면 receiver 가 data_type 가 2 인 것만 가져 갔기 때문에 메시지 큐가 포화되었기 때문입니다. 그래서 Ctrl-C 키로 receiver를 종료한 후에 main_reciever.c의 msgrcv() 인수 중 data_type를 0으로 변경한 후 다시 실행하면 큐에 쌓인 자료를 다시 읽어 들여서 큐를 비우게 되고 sender에서 다시 전송을 계속하게 되고 receiver도 수신을 계속하게 됩니다.

]$ gcc sender.c -o sender.out
]$ ./sender.out

main_reciever.c의 msgrcv()의 인수 중 data_type 를 0 으로 변경한 후 다시 실행해 보겠습니다.

////////////////////////// main_receiver.c
         :
   while( 1 ){
      // 메시지 큐 중에 data_type이 0 인 자료만 수신
      if ( -1 == msgrcv( msqid, &data, sizeof( t_data) - sizeof( long), 0, 0)){
         perror( "msgrcv() 실패");
         exit( 1);
      }
receiver sender
]$ gcc receiver.c -o receiver.out
]$ ./receiver.out
1 - type=1, ndx=1, http://badayak.com
2 - type=2, ndx=2, http://badayak.com
3 - type=3, ndx=3, http://badayak.com
4 - type=1, ndx=4, http://badayak.com
5 - type=2, ndx=5, http://badayak.com
6 - type=3, ndx=6, http://badayak.com
7 - type=1, ndx=7, http://badayak.com
8 - type=2, ndx=8, http://badayak.com
9 - type=3, ndx=9, http://badayak.com
10 - type=1, ndx=10, http://badayak.com
11 - type=2, ndx=11, http://badayak.com
12 - type=3, ndx=12, http://badayak.com
13 - type=1, ndx=13, http://badayak.com
                 :
]$ gcc sender.c -o sender.out
]$ ./sender.out


이 댓글을 비밀 댓글로