当前位置: 首页 > news >正文

Linux消息队列

常用函数

//创建/获取消息队列 
int msgget (key_t key, int msgflg);
/*
key : 为键值,ftok();
msgflg:
	IPC_CREAT - 创建,不存在即创建,已存在即获取,除非… 
	IPC_EXCL - 排斥,已存在即失败。
*/

// 向消息队列发送消息 
int msgsnd (int msqid, const void* msgp,size_t msgsz, int msgflg);
/*
msqid : msgget()返回
msgp : 包含消息类型和消息数据的内存块.前4个字节必须是一个大于0的整数,代表消息类型,其后消息数据
msgsz:不包括消息类型的,只算消息数据的内存大小
msgflg :IPC_NOWAIT内核中的消息队列缓冲区没有足够的空闲空间时,此函数不会阻塞,而是返回-1
*/

//从消息队列接收消息
ssize_t msgrcv (int msqid, void* msgp, size_t msgsz,long msgtyp, int msgflg);
/*
msqid : msgget()返回
msgp : 包含消息类型和消息数据的内存块
smgsz:接收的内存大小,如果接收到的内存>smgsz,则只会截取内存大小部分
msgtyp:
	=0 - 返回消息队列中的第一条消息。 
	>0 - 若msgflg参数不包含MSG_EXCEPT位,则返回消息队列中第一个类型为msgtyp的消息,若msgflg参数包含MSG_EXCEPT位,则返回消息队列中第一个类型不为msgtyp的消息。 
	<0 - 返回消息队列中类型小于等于msgtyp的绝对值的消息,若有多个,则取类型最小者。
*/

//销毁/控制消息队列 
int msgctl (int msqid, int cmd, struct msqid_ds* buf); 
/*
IPC_STAT 
获取消息队列的属性
IPC_SET 
设置消息队列的属性
IPC_RMID - 立即删除消息队列。 
 此时所有阻塞在对该消息队列的,msgsnd和msgrcv函数调用,都会立即返回失败,errno为EIDRM。

*/

例子

为了展示例程,部分代码删减,且多个文件合并了,开发过程中,请不要模仿,这样不规范。

server

#include "server.h"
#include "server_function.h"
#include "fileoper.h"
#include "slinklist.h"
#include <stdbool.h>
#include <signal.h>
#include <assert.h>
#include "client.h"

/*typedef struct Msg{
	int type;
	char msg[1024];
}Msg;

typedef struct Back{
	int type;
	char msg[1024];
}Back;*/
#define PATH "/home/zhizhen/项目/本地银行"
#define SERVER 100
#define CLIENT 101

int id1 ,id2;
Slink list = NULL;
Slink node = NULL;
void myexit(int sig){
	file_write(list);
	slink_destory(list);
	des_msg(id1);
	des_msg(id2);
	printf("退出成功\n");
	exit(0);
}
int server_run(){
	list = slink_create();
	assert(list != NULL);
	file_read(list);
	int id1 = create_msg(PATH,SERVER);
	int id2 = create_msg(PATH,CLIENT);
	assert(id1 != -1 && id2 != -1);
	while(1){	
		signal(SIGINT,myexit);
		Msg msg = {};//后面定义的,接收的消息的结构体
		Back back = {};
		int ret = 0;
		size_t msgsz = 0;
		 //接收消息
		ssize_t sz = recv_msg(id1,(void *)&msg,sizeof(msg.msg));
		assert(sz != -1);
		if(sz == 0){
			printf("该用户退出了\n");	
			node = NULL;
		}
		int opt = msg.type;
		switch(opt){
			case R:
				msgsz = recv_Reg(&msg,&back,list);
				break;
			case E:
				node = recv_Ent(&msg,&back,list);
				msgsz = sizeof(B_Ent);
				break;
			case G:
				msgsz = recv_GetM(&msg,&back,list,node);
				break;
			case S:
				msgsz = recv_SaveM(&msg,&back,list,node);
				break;
			case T:
				msgsz = recv_TranM(&msg,&back,list,node);
				break;
			case C:
				msgsz = recv_ChgP(&msg,&back,list,node);
				break;
			case D:
				msgsz = recv_Des(&msg,&back,list,node);
				break;
			}
			Slink next1 = list->next;
			int i = 1;
			while(next1 != NULL){
				Client *p = (Client *)(next1->elem);
				printf("-------------------\n");
				printf("*******%d*******\n",i);
				i++;
				printf("id:%s\n",p->id);
				printf("name:%s\n",p->name);
				printf("password:%s\n",p->password);
				printf("tel:%s\n",p->tel);
				printf("money:%d\n",p->money);
				printf("------------------\n");
				next1 = next1->next;
			}
			ret = send_msg(id2,(const void *)&back,msgsz);//发送反馈
			assert(ret != -1);
	}
}


client

#include "client.h"
#include <stdbool.h>
#include <assert.h>

static void menu(){
	printf("--------%d.注册\n",R);
	printf("--------%d.登录\n",E);
	printf("--------非%d和%d即:退出\n",R,E);
	printf(">>>>\n");
}

static void menu_Ent(){
	printf("******%d.取钱\n",G);
	printf("******%d.充值\n",S);
	printf("******%d.转账\n",T);
	printf("******%d.修改密码\n",C);
	printf("******%d.销户\n",D);
	printf("*******0.退出\n");
	printf(">>>>>\n");
}

/*typedef struct Msg{
	int type;
	char msg[1024];
}Msg;

typedef struct Back{
	int type;
	char msg[1024];
}Back;*/

int create_msg(char *s,int id){
	key_t key = ftok(s,id);
	assert(key != -1);
	return msgget(key,IPC_CREAT|0644);
}
int send_msg(int msqid,const void *msg,size_t msgsz){
	return msgsnd(msqid,msg,msgsz,0);
}
int recv_msg(int msqid,void *msg,size_t msgsz){
	return msgrcv(msqid,msg,msgsz,0,0);
}
int des_msg(int msqid){
	return msgctl(msqid,IPC_RMID,NULL);
}
int client_run(){
	int id1 = create_msg(PATH,SERVER);
	int id2 = create_msg(PATH,CLIENT);
	assert(id1 != -1 && id2 != -1);
Beg:
	while(1){
		Msg msg = {};
		size_t msgsz = 0;
		Back back = {};
		int ret = 0;
		menu();
		int opt = 0;
		scanf("%d",&opt);
		switch(opt){
			case R:
				msgsz = send_Reg(&msg);
				break;
			case E:
				msgsz = send_Ent(&msg);
				break;
			default:
				printf("退出成功\n");
				exit(0);
				break;
		}
			ret = send_msg(id1,(const void *)&msg,msgsz);
			assert(ret != -1);
			ret = recv_msg(id2,(void *)&back,sizeof(back.msg));
			assert(ret != -1);
			opt = back.type;
			switch(opt){
				case R:
					back_Reg(&back);
					break;
				case E:{
					if(back_Ent(&back) == 1){
						while(1){
							menu_Ent();
							int opt = 0;
							Msg msg = {};
							Back back = {};
							size_t msgsz = 0;
							scanf("%d",&opt);
							switch(opt){
								case G:
									msgsz = send_GetM(&msg);
									break;
								case S:
									msgsz = send_SaveM(&msg);
									break;
								case T:
									msgsz = send_TranM(&msg);
									break;
								case C:
									msgsz = send_ChgP(&msg);
									break;
								case D:
									msgsz = send_Des(&msg);
									break;
								default:
									goto Beg;
									printf("退出成功!\n");
									break;
							}
								ret = send_msg(id1,(const void *)&msg,msgsz);
								assert(ret != -1);
								ret = recv_msg(id2,&back,sizeof(back.msg));
								assert(ret != -1);
								opt = back.type;
								switch(opt){
									case G:
										back_GetM(&back);
										break;
									case S:
										back_SaveM(&back);
										break;
									case T:
										back_TranM(&back);
										break;
									case C:
										back_ChgP(&back);
										break;
									case D:
										back_Des(&back);
										break;
								}
							
						}
					}else{
						printf("登录失败!\n");
					}
					break;
				}
			}
	}
}

相关文章:

  • C盘满了,我用什么思路清理?
  • git add -u 什么意思
  • AEB滤镜再破碎,安全焦虑「解不开」?
  • Redis 持久化
  • 20个超实用的JavaScript高级技巧
  • 前端_we码
  • Java 8 简化代码(1)
  • Python-基础篇-类与对象/面向对象程序设计
  • 技术硬实力,阿里巴巴为什么要开源Spring Cloud Alibaba?
  • spring boot学习第八篇:kafka
  • 架设一台NFS服务器,并按照以下要求配置
  • openlayers [六] 地图交互 interaction 详解
  • 开源云真机平台-Sonic平台-python自定义脚本-config.json方式实现全局配置参数的读写操作
  • Redis的key过期策略是怎么实现的
  • 广和通AI解决方案“智”赋室外机器人迈向新天地!
  • 大数据StarRocks(八):集群扩缩容
  • Unity之四元数
  • C++系统笔记教程----vscode远程连接ssh
  • TCP的三次握手,四次挥手
  • vue列表飞入效果
  • 江西贵溪:铜板上雕出的国潮美学
  • 首次采用“顶置主星+侧挂从星”布局,长二丁“1箭12星”发射成功
  • 国务院办公厅印发《国务院2025年度立法工作计划》
  • 阿尔巴尼亚执政党连续第四次赢得议会选举,反对党此前雇用特朗普竞选经理
  • 线下哪些商家支持无理由退货?查询方法公布
  • 第1现场 | 印巴停火次日:当地民众逐渐恢复正常生活