- 操作系統的消息隊列的數目已達上限
- 創建的此消息隊列的ID已被佔用
進程間通信(二):消息隊列
消息隊列是操作系統爲兩個無關進程準備的通信方式,每個消息隊列都有一個他自己的ID我們用來標識消息隊列
消息隊列的不足就是我們發送消息的最大長度有限制,並且操作系統提供的消息隊列的個數也是有限的
此ID用如下函數創建
此函數中的path爲一個路徑,講道理這個路徑其實可以隨便定義,一般定義成當前目錄即可,然後這個proj_id就是一個數字而已可以隨便設,啊就是這樣,但是我們要知道同一個路徑同一個項目ID數完全有可能產生同一個消息隊列ID的,並且我們要注意的是消息隊列和管道不一樣,管道的生命隨進程,但是消息隊列的生命隨操作系統,所以當我們創建了一個新的消息隊列的話一定要手動的去銷燬,不然再次創建的話就有可能會失敗,那麼這我們介紹兩個命令
ipcs -q:查看所有的消息隊列
ipcrm -q id:刪除id的消息隊列
那現在我們知道創建消息隊列失敗的原因:
那我們用消息隊列來寫一個服務器和客戶端的相互通信
首先是關於消息隊列的一系列的函數
comm.h
#ifndef _COMM_H_
#define _COMM_H_
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
#define PATH_NAME "/tmp"
#define PROJ_ID 0x6666
//創建消息隊列
#define SERVER_TYPE 1
#define CLIENT_TYPE 2
//此時我們用msgbuf是顯示重定義
//應該是在頭文件裏的msg緩衝區定義爲msgbuf
//我們將我們的名字換一下即可
struct msgbuff
{
long mtype;
char mtext[128];
};
int createMsgQueue();
//創建消息隊列
int getMsgQueue();
//獲得消息隊列
int sendMsg(int msgid,char *msg,int t);
//發送消息隊列
//接受消息隊列
int recvMsg(int msgid,char *msg,int t);
//銷燬消息隊列
void destoryMsgQueue(int msgid);
#endif
comm.c
#include "comm.h"
int commMsgQueue(int flag)
{
key_t k = ftok(PATH_NAME,PROJ_ID);
if(k < 0)
{
printf("ftok error!!");
return -1;
}
int msgid = msgget(k,flag);
if(msgid < 0)
{
printf("msgget error!!");
return -2;
}
return msgid;
}
int createMsgQueue()
{
return commMsgQueue(IPC_CREAT|IPC_EXCL|0644);
}
int getMsgQueue()
{
return commMsgQueue(IPC_CREAT);
}
void destoryMsgQueue(int msgid)
{
if(msgctl(msgid,IPC_RMID,NULL) < 0)
{
printf("msgctl error!!");
}
}
//發送數據塊
//msgid(消息隊列的標識符),msg(數據塊結構體的地址),
//msgsz(數據塊裏數組的字節大小),msgflg(判斷是阻塞式還是非阻塞式)
//int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
int sendMsg(int msgid,char *msg,int t)
{
struct msgbuff buf;
buf.mtype = t;
strcpy(buf.mtext,msg);
if(msgsnd(msgid,&buf,sizeof(buf.mtext),0) < 0)
{
printf("msgsnd error!\n");
return -1;
}
return 0;
}
//接收數據塊
//msgtyp(數據塊內容的類型)
//ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
//msg:要發送的數據
int recvMsg(int msgid,char *msg,int t)
{
struct msgbuff buf;
if(msgrcv(msgid,&buf,sizeof(buf.mtext),t,0) < 0)
{
perror("msgrcv error!\n");
return -1;
}
strcpy(msg,buf.mtext);
return 0;
}
接下來是我們的服務器和客戶端的代碼
因爲服務器端是先接受消息,再發送消息
//server.c
#include"comm.h"
int main()
{
int msgid = createMsgQueue();
//printf("%d",msgid);
char buf[256];
while(1)
{
if(strcmp(buf,"quit") == 0)
{
printf("client quit\n");
break;
}
recvMsg(msgid,buf,CLIENT_TYPE);
printf("client #%s\n",buf);
printf("Please enter:");
scanf("%s",buf);
sendMsg(msgid,buf,SERVER_TYPE);
}
destoryMsgQueue(msgid);
return 0;
}
客戶端是先發送消息再接收消息
//client.c
#include"comm.h"
int main()
{
int msgid = getMsgQueue();
//先發消息
char buf[256];
while(1)
{
printf("Please enter :");
scanf("%s",buf);
sendMsg(msgid,buf,CLIENT_TYPE);
if(strcmp("quit",buf) == 0)
{
printf("client quit!");
}
recvMsg(msgid,buf,SERVER_TYPE);
printf("server #%s\n",buf);
}
destoryMsgQueue(msgid);
return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.