您好,登錄后才能下訂單哦!
原實例在APUE(第三版)17.2 UNIX域套接字
1、使用UNIX與套接字輪詢XSI消息隊列(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 //消息隊列的第一個key值 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 (;;) { printf("helper qid %d, fd %d, tid %u\n", tip->qid, tip->fd, (unsigned)pthread_self()); 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 %d ID is %d\n", i, qid[i]); if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fd) < 0) { //創建UNXI域套接字(fd管道) err_sys("socketpair error"); } printf("fd[0]:%d\n", fd[0]); printf("fd[1]:%d\n", fd[1]); 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"); } for (i = 0; i < NQ; ++i) { //printf("i:%d\n", 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 %d id %d, message %s\n", i, qid[i], buf); } } } exit(0); }
編譯命令:
gcc pollmsg.c -o pollmsg -lapue -lpthread -std=c99
2、使用UNIX與套接字輪詢XSI消息隊列(epoll版,改版)
#include "apue.h" #include <pthread.h> #include <sys/msg.h> #include <sys/socket.h> #include <sys/epoll.h> #define NQ 3 //隊列的數量 #define MAXMSZ 512 //消息的最大長度 #define KEY 0x123 //消息隊列的第一個key值 #define FDSIZE 1000 #define EPOLLEVENTS 100 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 (;;) { printf("helper qid %d, fd %d, tid %u\n", tip->qid, tip->fd, (unsigned)pthread_self()); 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]; int epollfd; struct epoll_event events[EPOLLEVENTS]; struct threadinfo ti[NQ]; pthread_t tid[NQ]; char buf[MAXMSZ]; epollfd = epoll_create(FDSIZE); //創建epoll文件描述符 for (i = 0; i < NQ; ++i) { if ((qid[i] = msgget((KEY+i), IPC_CREAT|0666)) < 0) { //創建一個新隊列 err_sys("msgget error"); } printf("queue %d ID is %d\n", i, qid[i]); if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fd) < 0) { //創建UNXI域套接字(fd管道) err_sys("socketpair error"); } struct epoll_event ev; ev.events = EPOLLIN; ev.data.fd = fd[0]; epoll_ctl(epollfd, EPOLL_CTL_ADD, fd[0], &ev); //注冊fd[0]到epoll 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 (;;) { int occurred; if ((occurred = epoll_wait(epollfd, events, EPOLLEVENTS, -1)) < 0) { //等待事件發生 err_sys("epoll error"); } if (occurred == 0) { err_sys("epoll timeout"); } for (i = 0; i < occurred; ++i) { if (events[i].events & EPOLLIN) { if ((n = read(events[i].data.fd, buf, sizeof(buf))) < 0) { err_sys("read error"); } buf[n] = 0; printf("main thread %u, message %s\n", (unsigned)pthread_self(), buf); } } } exit(0); }
編譯命令:
gcc epollmsg.c -o epollmsg -lapue -lpthread -std=c99
3、給XSI消息隊列發送消息(測試程序,原版)
#include "apue.h" #include <sys/msg.h> #define MAXMSZ 512 struct 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); //printf("key:0x%08X\n", (unsigned )key); 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; //printf("qid:%ld\n", qid); if (msgsnd(qid, &m, nbytes, 0) < 0) { //發送消息給指定消息隊列 err_sys("can't send message"); } exit(0); }
編譯命令:
gcc sendmsg.c -o sendmsg -lapue -std=c99
相關閱讀:
1、select、poll、epoll之間的區別總結[整理]
2、poll函數的使用,原文
3、APUE讀書筆記
*** walker ***
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。