UNIX域套接字轮询XSI消息队列
来源:互联网 发布:淘宝怎么拒收退款流程 编辑:程序博客网 时间:2024/05/22 02:06
UNIX域套接字用于在同一台计算机上运行的进程之间的通信。这点比用因特网域套接字效率更高。因为UNIX域套接字仅仅复制数据,并不执行协议处理,不要添加或删除网络报头,无需计算校验和, 不要产生顺序号,无需发送确认报文。 UNIX域套接字提供流和数据包两种接口。UNIX域数据报服务是可靠的,既不会丢失报文,也不会传递出错。UNIX域套接字就像是套接字和管道的混合。可以使用它们面向网络的域套接字接口或使用socketpair函数创建一对无命名的、相互连接的UNIX域套接字。
#include <sys/socket.h>int socketpair(int domain, int type, int protocol, int sockfd[2]); 返回值: 若成功,返回0; 若出错,返回-1
一对相互连接的UNIX域套接字可以起到全双工通道的作用:两端对读写都开放。
消息队列是XSI IPC三种方式之一(其他两个:信号量、共享存储)。每个内核中的IPC结构都用一个非负整数的标识符加以引用。例如, 要向一个消息队列发送消息或者从一个消息队列取消息,只需要知道其队列标识符。与文件描述符不同,IPC标识符不是小的整数。 当一个IPC结构被创建时,与这种结构相关的标识符连续加1,直至达到一个整型数的最大正值,然后又回转到0。
标识符是IPC对象的内部名。为使多个合作进程能够在同一IPC对象上汇聚,提供了一个外部命名方案。 每个IPC对象都与一个键相关联,将这个键作为该对象的外部名。当创建一个新IPC结构时,都应该指定一个键,这个键的数据类型是基本系统数据类型key_t.
但是,消息队列不能关联到文件描述符,这就限制了它不能和poll或select函数一起使用。然而,套接字是和文件描述符相关联的,消息到达时,可以用套接字来通知。对每一个消息队列使用一个线程。每个线程都会在msgrcv调用中阻塞。当消息到达时,线程会把它写入一个UNIX域套接字的一端。当poll指示套接字可以读数据时,应用程序会使用这个套接字的另一端接收消息。
// 17-3.c//使用UNIX域套接字轮询 XSI消息队列#include "apue.h"#include "myerror.h"#include <pthread.h>#include <sys/msg.h>#include <sys/socket.h>#include <sys/poll.h>#define NQ 3 /* number of queues */#define MAXMSZ 512 /* maximum message size */#define KEY 0x123 /* key for first message queue */struct threadinfo{ int qid; int fd;};struct mymesg{ long mtype; char mtext[MAXMSZ];};void *helper(void *arg){ int n; struct mymesg m; struct threadinfo *tip = arg; for (;;) { memset(&m, 0, sizeof(m)); if ((n = msgrcv(tip->qid, &m, MAXMSZ, 0, MSG_NOERROR)) < 0) err_sys("msgrcv error"); if (write(tip->fd, m.mtext, n) < 0) err_sys("write error"); }}int main(){ int i, n, err; int fd[2]; int qid[NQ]; struct pollfd pfd[NQ]; struct threadinfo ti[NQ]; pthread_t tid[NQ]; char buf[MAXMSZ]; for (i = 0; i < NQ; i++) { if ((qid[i] = msgget((KEY+i), IPC_CREAT | 0666)) < 0) err_sys("msgget error"); printf("queue ID %d is %d\n", i, qid[i]); if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fd) < 0) err_sys("socketpair error"); // 使用的是数据包套接字而不是流套接字,这样做可以保持消息边界,以保证从套接字里一次只读取一条消息 pfd[i].fd = fd[0]; pfd[i].events = POLLIN; ti[i].qid = qid[i]; ti[i].fd = fd[1]; if ((err = pthread_create(&tid[i], NULL, helper, &ti[i])) != 0) err_exit(err, "pthread_create error"); } for (;;) { if (poll(pfd, NQ, -1) < 0) err_sys("poll error"); printf("\n"); for (i = 0; i < NQ; i++) { if (pfd[i].revents & POLLIN) { if ((n = read(pfd[i].fd, buf, sizeof(buf))) < 0) err_sys("read error"); buf[n] = 0; printf("queue id %d, message %s\n", qid[i], buf); } } } exit(0);}
在main函数中创建了一些消息队列和UNIX域套接字,并为每个消息队列开启了一个线程。然后它在一个无线循环中用poll来论询选择一个套接字端点。当某个套接字可读时,程序从套接字中读取数据并把消息打印到标准输出上。
//17-4.c//给XSI消息队列发送消息//程序需要两个参数: 消息队列关联的键值以及一个包含消息主体的字符串。#include "apue.h"#include "myerror.h"#include <sys/msg.h>#define MAXMSZ 512struct mymesg{ long mtype; char mtext[MAXMSZ];};int main(int argc, char *argv[]){ key_t key; long qid; size_t nbytes; struct mymesg m; if (argc != 3) { fprintf(stderr, "usage: sendmsg KEY message\n"); exit(1); } key = strtol(argv[1], NULL, 0); if ((qid = msgget(key,0)) < 0) err_sys("can't open queue key %s", argv[1]); memset(&m, 0, sizeof(m)); strncpy(m.mtext, argv[2], MAXMSZ-1); nbytes = strlen(m.mtext); m.mtype = 1; if (msgsnd(qid, &m, nbytes, 0) < 0) err_sys("can't send message"); exit(0);}
测试结果:
- UNIX域套接字轮询XSI消息队列
- UNIX域套接字轮询XSI消息队列
- Linux XSI IPC 之消息队列
- XSI进程间通信---消息队列
- XSI IPC之消息队列实例
- XSI IPC(消息队列、信号量、共享内存)
- XSI IPC——System V消息队列
- 【Linux/OS/Network】XSI IPC(消息队列,信号量,共享内存)
- XSI消息队列与复用IO的结合实例
- unix 消息队列
- UNIX消息队列
- UNIX消息队列
- unix线程消息队列
- Unix域套接字
- UNIX域套接字
- UNIX域套接字
- Unix域套接字
- unix域套接----详解
- C#第一步
- C/C++中&符号的用法
- JAVA socket 简单示例
- 关于angularjs中ngOptions的简单介绍
- Android 流量球效果的WaveView
- UNIX域套接字轮询XSI消息队列
- Classification-对评价分类
- Mapper.xml解析
- 使用静态方法,可以用来计数用
- 研究生学习要会熟练运用三个工具
- HTML 5 参考手册(视频/音频)
- opencv cvcopy() error :assertion faild (src.depth()==dst.depth()&&src.size==dst.size)
- 论文松”少女萌萌拳”为何风靡全国 创意制胜
- Kafka设计解析(二):Kafka High Availability (上)