1、UNIX域套接字-在同一计算机系统上运行的两个进程之间传送打开文件描述符。仅仅复制数据不需要执行协议处理。消息队列不能和poll或者select一起使用(只要多个消息队列中一个消息发生)。
//创建一对无命名的、相互连接的UNIX域套接字,可以起到全双工管道的作用
int socketpair(int domain, int type, int protocol, int sockfd[2]);
2、
/*
服务器创建3个线程,每个线程接受消息,把消息写入套接字
多个套接字由poll选择,如果有消息则从该套接字输出消息到终端
*/
#include "apue.h"
#include <poll.h>
#include <pthread.h>
#include <sys/msg.h>
#include <sys/socket.h>
#define NQ 3 //队列数量
#define MAXMSZ 512 //消息的最大长度
#define KEY 0x123
//为传送给线程的参数定义结构
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));
//从消息队列接收消息
n = msgrev(tip->qid, &m, MAXMSZ, 0, MSG_NOERROR);
//把消息写到套接字中
write(tip->fd, m.mtext, n);
}
}
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++)
{
//创建消息队列,返回队列ID
qid[i]=msgget((KEY+i),IPC_CREAT|0666);
printf("queue ID%d is %d\n",i,qid[i]);
//创建UNIX域套接字
socketpair(AF_UNIX, SOCK_DGRAM, 0, fd);
pfd[i].fd = fd[0];//套接字可读端的一段放在poll中
pfd[i].event = POLLIN;
//封装传给线程的参数
ti[i].qid=qid[i];
ti[i].fd=fd[i];
pthread_create(&tid[i], NULL, helper, &ti[i]);
}
for(;;)
{
poll(pfd, NQ, -1);//如果套接字中都没有消息,则挂起
for(i=0;i<NQ;i++)
{
if(pid[i].revents & POLLIN)//找到有消息的套接字
n=read(pfd[i].fd, buf, sizeof(buf));
buf[n]='\0';
printf("queue id %d, message %s\n", qid[i], buf)
}
}
exit(0);
}
3、
/*
客户端向对应消息队列发送消息
*/
#include "apue.h"
#include <sys/msg.h>
#define MAXMSZ 512 //消息的最大长度
//一个消息队列结构
struct mymesg{
long mtype;
char mtext[MAXMSZ];
};
//argv[1]为消息队列对应的key值, argv[2]为要发送的消息
int main(int argc, char *argv[])
{
key_t key;
long qid;
size_t nbytes;
struct mymesg m;
key=strtol(argv[1],NULL ,0);//把输入的字符串转化为数值
qid=msgget(key, 0); //根据key值得到对应的消息队列ID
memset(&m, 0, sizeof(m));
strncpy(m.mtext, argv[2],MAXMSZ-1);
nbytes=strlen(m.mtext);
m.mtype=1;
msgsnd(qid, &m, nbytes,0);
exit(0);
}
4、命名UNIX域套接字
无关进程不能使用没有名字的套接字。
//struct sockaddr_un即套接字地址(服务地址),bind就是把创建的套接字(返回文件描述符)和这个地址绑定
struct sockaddr_un{
sa_family_t sun_family;
char sun_path[108];
};
5、传送文件描述符
文件描述符是指向文件表项的指针。当两个进程打开相同文件时,他们文件描述符指向不同的表项,表项指向相同V节点。传送文件描述符使不同进程的文件描述符(不一定相同)执行相同的文件表项。