本篇利用消息队列的特性实现简单的聊天程序,msgsnd发送数据,msgrcv接收数据来实现聊天功能,消息队列详情。
数据接收端msgrcv
//这是一个以system V消息队列实现的聊天程序客户端
//// 1.创建消息队列
//// 2.从消息队列中获取一个数据,打印出来
//// 3.从标准输入中获取一个数据,组织成消息队列节点发送
//// 4.删除消息队列
//// 接口:
//// 创建 msgget
//// 接收数据 msgrcv
//// 发送数据 msgsnd
//// 控制 msgctl
//// int msgget(key_t key,int msgflg);
//// msgflg:
//// key:内核中消息队列的标识
//// IPC_CREAT 不存在则创建,存在则打开
//// IPC_EXCL 与IPC_CREAT 同用,若存在则报错 防止程序重复启动
//// mod 权限
//// 返回值:一个代码操作的句柄:失败:-1
//// ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
//// int msgflg);
//// msgid:msgget返回的操作句柄
//// smgp:用于接收数据
//// msgsz:指定接收的数据大小
//// msgtyp:指定接收的数据类型
//// msgflg:标准选项,0
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#define IPC_KEY 0x12345678
//下面两个宏,用于我们赋值我们传输的数据块类型
#define TYPE_S 1
#define TYPE_C 2
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1024]; /* message data */
};
int main()
{
int msgid=-1;
//ftok
// //key_t ftok(const char *pathname, int proj_id);
// //ftok通过文件的inode节点号和一个proj_id计算出一个key值
// //缺点:如果文件被删除,或者替换,那么将打开的不是同一个消息队列
//
//1.创建消息队列
msgid=msgget(IPC_KEY,IPC_CREAT | 0664);
if(msgid<0){
perror("msgget error");
return -1;
}
while(1){
//2.接收数据
//struct msgbuf这个结构体需要我们自己定义
struct msgbuf buf;
//msgrcv:默认阻塞的获取数据
//msgid:操作句柄
//
//buf:接收数据的结构体,自己定义
//1024 用于指定接收的数据的最大长度,不包含mtype
//TYPE_C 用于指定接收的数据类型
//msgflag 0默认
// MSG_NOERROR 当数据长度超过指定长度,则截断数据
msgrcv(msgid,&buf,1024,TYPE_C,0);
printf("client say:%s\n",buf.mtext);
//发送数据
memset(&buf,0x00,sizeof(struct msgbuf));
buf.mtype=TYPE_S;
scanf("%s",buf.mtext);
msgsnd(msgid,&buf,1024,0);
}
msgctl(msgid,IPC_RMID,NULL);
return 0;
}
数据发送端msgsnd
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#define IPC_KEY 0x12345678
//下面两个宏,用于我们赋值我们传输的数据块类型
#define TYPE_S 1
#define TYPE_C 2
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1024]; /* message data */
};
int main()
{
int msgid=-1;
//ftok
// //key_t ftok(const char *pathname, int proj_id);
// //ftok通过文件的inode节点号和一个proj_id计算出一个key值
// //缺点:如果文件被删除,或者替换,那么将打开的不是同一个消息队列
//
//1.创建消息队列
msgid=msgget(IPC_KEY,IPC_CREAT | 0664);
if(msgid<0){
perror("msgget error");
return -1;
}
while(1){
struct msgbuf buf;
//发送数据
memset(&buf,0x00,sizeof(struct msgbuf));
buf.mtype=TYPE_C;
scanf("%s",buf.mtext);
msgsnd(msgid,&buf,1024,0);
//2.接收数据
//struct msgbuf这个结构体需要我们自己定义
//msgrcv:默认阻塞的获取数据
//msgid:操作句柄
//
//buf:接收数据的结构体,自己定义
//1024 用于指定接收的数据的最大长度,不包含mtype
//TYPE_C 用于指定接收的数据类型
//msgflag 0默认
// MSG_NOERROR 当数据长度超过指定长度,则截断数据
msgrcv(msgid,&buf,1024,TYPE_S,0);
printf("server say[%s]\n",buf.mtext);
}
msgctl(msgid,IPC_RMID,NULL);
return 0;
}