主页 > IT业界  > 

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; } } } }
标签:

Linux消息队列由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Linux消息队列