Linux C 消息队列实现简单的聊天功能 您所在的位置:网站首页 linux多人聊天室 Linux C 消息队列实现简单的聊天功能

Linux C 消息队列实现简单的聊天功能

2024-06-29 11:46| 来源: 网络整理| 查看: 265

消息队列是提供一种带有数据标识的特殊管道,使得每一段被写入的数据都变成带标识的消息,读取该段消息的进程只要指定这个标识就可以正确地读取,而不会受到其他消息的干扰,。一个带标识的消息队列,就像并存的管道一样。这里主要介绍的是利用线程和消息队列,写两个进程,实现两个进程之间的聊天功能。

使用方法:

       发送者:首先要获取消息队列的ID号,然后将数据放入一个带有标识的结构体内,最后把消息发送到消息队列中。

       接收者:首先也是要获取到消息队列的ID号,然后把带有指定标识的数据读出来。

所需要用到的函数有:

#include

#include

 key_t ftok(const char *pathname, int proj_id);    第一个参数是一个已存在的路径,第二个参数可以自定义。只要两个进程中的两个参数是相同的,那么生成的key值也是相同的。

include

#include

#include

返回值:成功则返回合法的key值;失败返回-1。

 

int msgget(key_t key, int msgflg);

第一个参数就是通过ftok函数生成的key值,第二个参数:

IPC_CREAT 如果在内核中不存在该队列,则创建它。 IPC_EXCL 当与IPC_CREAT一起使用时,如果队列早已存在则将出错。同时可以指定MSG的访问权限,如(0666);

返回值:成功则返回消息队列的ID,失败就返回-1;

如msgget(key,IPC_CREATE | 0666 )就表示,如果key值对应的消息队列不存在就创建,存在就获取消息队列的ID。权限只有读写,所以0777和0666是一样的。没有执行的权限。

发送和接收函数:

#include

#include

#include

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);

 

msgsnd();第一个参数为消息队列的ID号;第二个参数为要发送数据的存储区指针。

第三个参数为要接收数据的大小。

最有一个参数:msgflg

  MSG_NOERROR    若返回的消息比msgsz字节多,则消息会截断到msgsz字节,且不通知消息发送进程

IPC_NOWAIT 若消息队列中无对应类型的消息接收则立即返回

阻塞等待直至接收到一条相应类型的消息为止

一般都写0,阻塞等待。

msgrcv()函数与magsnd()函数的参数相同,除了mystype。这个是接收函数独有的。代表要接收消息的标识。

发送消息的时候,消息必须要被组织为以下的形态:

struct massage

{

       long type;       //消息的标识

       char text[80];     //消息的正文,大小可自定义。

 

};

发送的消息必须要有一个标识在前面,后面的数据则没有要求。

msgctl()

#include

#include

#include

  int msgctl(int msqid, int cmd, struct msqid_ds *buf);

第一个参数为消息队列的ID;

第二个参数:

IPC_STAT:把msgid_ds结构中的数据设置为消息队列的当前关联值,即用消息队列的当前关联值覆盖msgid_ds的值。

    IPC_SET:如果进程有足够的权限,就把消息列队的当前关联值设置为msgid_ds结构中给出的值

IPC_RMID:删除消息队列

IPC_INFO:获得当前系统中MSG的限制值信息

MSG_INFO:获得当前系统中MSG的相关资源消耗的信息

MSG_STAT:获取系统中所有消息队列的信息。

最后一个参数为相关结构体缓存区。

具体代码如下。需要注意的是,发送数据的函数需要写在主线程中,接收函数写在创建线程中,这样才能做到随时进行数据的传输。分别编译a.c和b.c,然后同时运行两个可执行文件就可以了。编译时记得链接线程库。两个程序的主要区别就在于接收和发送的信息标识。

a.c #include #include #include #include #include #include #include struct massage { long type; char text[80]; }; struct massage buf; int msgid; void *recive(void *p) { struct massage buf2; while (1) { bzero(&buf2,sizeof(buf2)); msgrcv(msgid,&buf2,sizeof(buf2),100,0); //阻塞等待mytype为100的值 printf("%s",buf2.text); } return 0; } int main() { key_t key=ftok("/home/rchris520/haha",300); msgid=msgget(key, IPC_CREAT|0666); pthread_t pid; pthread_create(&pid,NULL,recive,NULL); //创建一个线程运行接收函数 while(1) { bzero(&buf,sizeof(buf)); buf.type = 200; fgets(buf.text,sizeof(buf.text),stdin); msgsnd(msgid,&buf,sizeof(buf),0); } msgctl(msgid, IPC_RMID, 0); return 0; } b.c #include #include #include #include #include #include #include struct massage { long type; char text[80]; }; struct massage buf; int msgid; void *recive(void *p) { struct massage buf2; while(1) { bzero(&buf2,sizeof(buf2)); msgrcv(msgid,&buf2,sizeof(buf2),200,0); //阻塞等待mytype为200的值 printf("%s",buf2.text); } return 0; } int main() { key_t key=ftok("/home/rchris520/haha",300); msgid=msgget(key, IPC_CREAT|0666); // 创建消息队列 pthread_t pid; pthread_create(&pid,NULL,recive,NULL); // 创建线程 while(1) { bzero(&buf,sizeof(buf)); buf.type=100; fgets(buf.text,sizeof(buf.text),stdin); //主线程输入消息 msgsnd(msgid,&buf,sizeof(buf),0); // 发送消息 } msgctl(msgid, IPC_RMID, 0); return 0; }

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有