歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

消息隊列的簡單實現

消息隊列:一個進程向另一個進程發送數據塊
消息隊列基於消息,管道基於字節流
 
消息隊列是用鏈表實現
 
1.創建:int megget(key_t key, int msgflag)
    key:函數ftok()的返回值
    msgflag:IPC_CREAT是創建新的消息隊列;IPC_EXCL與IPC_CREAT一起使用,即如果要創建的消息隊列已存在,則返回錯誤
    成功:返回隊列標識符
    失敗:-1
2.獲取:ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
    msqid:消息隊列的識別碼
    msgp:指向消息緩沖區的指針,用來暫時存儲發送和接收的消息,是用戶自己定義的一個通用結構
        struct msgbuf
        {
            long mtype;  //消息類型,必須> 0
            char mtext[__SIZE__];  //消息文本
        }
    msgsz:消息大小
    msgtyp:消息類型(>0,返回其類型為mtype的第一個消息)
    msgflg:控制函數行為(0表示忽略)
 
    成功:返回拷貝到mtext數組的實際字節數
    失敗:-1
3.發送:int msgsnd(int msqid, void *msgp, size_t msgsz, int msgflg)
    成功:返回0
    失敗:-1
4.設置屬性:int msgctl(int msqid, int cmd, struct msqid_ds *buf)
    對msqid標識的消息隊列執行cmd操作
    cmd操作:IPC_STAT(獲取對應的msqid_ds的數據結構,保存在buf指定的地址空間)
        IPC_SET(設置消息隊列的屬性,保存在buf中)
        IPC_RMID(從內核刪除msqid標識的消息隊列)
    msqid_ds:描述隊列當前狀態
    成功:0
    失敗:-1
 
 
comm.h
#ifndef __COMM__
#define __COMM__
 
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <string.h>
 
#define __SIZE__ 1024
#define FILEPATH "/tmp/.msg1"
#define ID 0
 
 
const int ser_send_type=1;
const int cli_send_type=2;
 
typedef struct msg_info
{
    char mtext[__SIZE__];
    long mtype;
}msginfo;
 
 
#endif
 
client.h
#ifndef __CLIENT__
#define __CLIENT__
 
#include "comm.h"
 
int cli_start();
int cli_end(int);
 
#endif
client.c
#include "client.h"
 
int msg_id= -1;
 
int cli_start()
{
 
    //create the client's buf which storage the msg
    msginfo cli_info;
 
    //create the key
    key_t key= ftok(FILEPATH, ID);
    if(key< 0)
    {
        perror("ftok");
        exit(1);
    }
    //get the ID of msg_queue
    msg_id= msgget(key, 0);
    if(msg_id< 0)
    {
        perror("cli get key id failed");
        exit(2);
    }
 
    while(1)
    {
        //client said
        printf("client:>");
        fgets(cli_info.mtext, __SIZE__, stdin);  //write in the cli_info
        //when it will exit?
        if(strncasecmp(cli_info.mtext, "quit", 4)==0)
        {
            printf("client bye!\n");
            break;
        }
        cli_info.mtype= cli_send_type;
        //send the msg(send judge)
        if(msgsnd(msg_id, &cli_info, sizeof(cli_info.mtext),0)== -1) //send fail
        {
            perror("client send msg fail");
            exit(3);
        }
 
        //receive the msg
        memset(cli_info.mtext, '\0', sizeof(cli_info.mtext));  //reset first
        if(msgrcv(msg_id, &cli_info, sizeof(cli_info.mtext), ser_send_type, 0)==-1)  //receive fail
        {
            perror("client msgrcv fail");
            exit(4);
        }
        printf("server:>%s\n", cli_info.mtext);  //the msg receive from server have storaged in the cli_info.mtext
        fflush(stdout);
    }
    return 0;
}
int cli_end(int id)
{
    if(msgctl(id, IPC_RMID, NULL)==-1)  //fail
    {
        perror("delete th msg_queue from kernel fail");
        exit(5);
    }
    else
    {
        printf("delete the msg_queue from kernel success\n");
        return 0;
    }
}
static void delete_msg(void)
{
    if(msg_id!= -1)  //the msg_queue exist
    {
        cli_end(msg_id);
    }
    printf("delete the msg queue end\n");
}
int main(int argc,char *argv[])
{
    atexit(delete_msg);
    if(cli_start()==0)
    {
        printf("cli start success\n");
    }
    else
    {
        printf("cli start failed\n");
    }
    return 0;
}
 
server.h
#ifndef __SERVER__
#define __SERVER__
 
#include "comm.h"
 
int ser_start();
int ser_end(int);
 
#endif
server.c
#include "server.h"
 
int msg_id= -1;
int ser_start()
{
 
    //create the server's buf which storage the msg
    msginfo ser_info;
 
    //create the key
    key_t key= ftok(FILEPATH, ID);
    if(key< 0)
    {
        perror("ftok");
        exit(1);
    }
    //get the ID of msg_queue
    msg_id= msgget(key, IPC_CREAT|IPC_CREAT|0666);
    if(msg_id< 0)
    {
        perror("ser get key id failed");
        exit(2);
    }
 
    while(1)
    {
        //reveive the msg
        if(msgrcv(msg_id, &ser_info, sizeof(ser_info.mtext), cli_send_type, 0)==-1) //fail
        {
            perror("server msgrcv fail");
            exit(3);
        }
        printf("client:>%s\n",ser_info.mtext);  //first,output the client's msg
 
        printf("server:>");  //then,server will said
        memset(ser_info.mtext, '\0', sizeof(ser_info.mtext));  //reset first
        fgets(ser_info.mtext, __SIZE__, stdin);  //write in the ser_info
        //when it will exit?
        if(strncasecmp(ser_info.mtext, "quit", 4)==0)
        {
            printf("server bye!\n");
            break;
        }
        ser_info.mtype= ser_send_type;
        //send the msg
        if(msgsnd(msg_id, &ser_info, __SIZE__, 0)==-1)  //fail
        {
            perror("server msgsnd fail");
            exit(4);
        }
        fflush(stdout);
    }
    return 0;
}
int ser_end(int id)
{
    if(msgctl(id, IPC_RMID, NULL)== -1)  //fail
    {
        perror("delete the msg_queue from kernel fail");
        exit(5);
    }
    else
    {
        printf("delete the msg_queue from kernel success\n ");
        return 0;
    }
}
static void delete_msg(void)
{
    if(msg_id!= -1)  //the msg_queue exist
    {
        ser_end(msg_id);
    }
    printf("delete the msg_queue end\n");
}
int main(int argc, char *argv[])
{
    atexit(delete_msg);
    if(ser_start()==0)  //success
    {
        printf("ser start success\n");
    }
    else
    {
        printf("ser start failed\n");
    }
    return 0;
}
 
Makefile
.PHONY:all
all:client server
client:client.c
    gcc -o $@ $^
server:server.c
    gcc -o $@ $^
.PHONY:clean
clean:
    rm -f client server

Copyright © Linux教程網 All Rights Reserved