練習1:
? ? ?使用消息隊列實現的2個終端之間的互相聊天 并使用信號控制消息隊列的讀取方式: 當鍵盤按ctrl+c的時候,切換消息讀取方式,一般情況為讀取指定編號的消息,按ctrl+c之后,指定的編號不讀取,讀取其他所有編號的消息
//聊天一號機位 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> #include <semaphore.h> #include <wait.h> #include <signal.h> #include <sys/socket.h> #include <arpa/inet.h> #include <sys/socket.h> #include <sys/ipc.h> #include <sys/sem.h> #include <semaphore.h> #include <sys/msg.h> #include <sys/shm.h> #include <sys/un.h> //定義結構體 struct msgbuf{long mtype;char mtext[128]; }; int msgid; int signal_l=0;//ctrl+c改變的變量信息編號 int s=0;//用來判斷切換回去的變量 void handle(int sig){if(s==0){signal_l=020000;s=1;}else if(s!=0){signal_l=0;s=0;} } //用于讀取的線程 void *ltread(void *arg){signal(SIGINT,handle);struct msgbuf rbuf;while(1){memset(&rbuf,0,sizeof(rbuf));//初始化結構體msgrcv(msgid,&rbuf,128,2,signal_l);//讀取消息隊列中的消息printf("讀取到的消息為%s\n",rbuf.mtext);} } int main(int argc, const char *argv[]) {//調用函數ftok,獲取訪問同一個消息隊列的秘鑰key_t key;if((key=ftok("liantianle",100))==EOF){perror("ftok");return -1;}//根據秘鑰創建消息隊列/根據秘鑰訪問一個已經存在的消息隊列if((msgid=msgget(key,IPC_CREAT|0666))==EOF){perror("msgget");return -1;}//創建并運行一個線程pthread_t thread;if((thread=pthread_create(&thread,NULL,ltread,NULL))!=0){perror("pthread_create");return -1;}struct msgbuf wbuf;signal(SIGINT,SIG_IGN);while(1){memset(&wbuf,0,sizeof(wbuf));//初始化結構體wbuf.mtype=1;//確定消息編號printf("1號輸入:");fgets(wbuf.mtext,128,stdin);//直接讀取終端輸入,避免了scanf不吸收空格的影響msgsnd(msgid,&wbuf,strlen(wbuf.mtext),0);//將消息寫入消息隊列,以阻塞的形式}return 0; }// 聊天2號機位 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> #include <semaphore.h> #include <wait.h> #include <signal.h> #include <sys/socket.h> #include <arpa/inet.h> #include <sys/socket.h> #include <sys/ipc.h> #include <sys/sem.h> #include <semaphore.h> #include <sys/msg.h> #include <sys/shm.h> #include <sys/un.h> //定義結構體 struct msgbuf{long mtype;char mtext[128]; }; int msgid; int signal_l=0;//ctrl+c改變的變量信息編號 int s=0;//用來判斷切換回去的變量 void handle(int sig){if(s==0){signal_l=020000;s=1;}else if(s!=0){signal_l=0;s=0;} } //用于讀取的線程 void *ltread(void *arg){signal(SIGINT,handle);struct msgbuf rbuf;while(1){memset(&rbuf,0,sizeof(rbuf));//初始化結構體msgrcv(msgid,&rbuf,128,1,signal_l);//讀取消息隊列中的消息printf("讀取到的消息為%s\n",rbuf.mtext);} } int main(int argc, const char *argv[]) {//調用函數ftok,獲取訪問同一個消息隊列的秘鑰key_t key;if((key=ftok("liantianle",100))==EOF){perror("ftok");return -1;}//根據秘鑰創建消息隊列/根據秘鑰訪問一個已經存在的消息隊列if((msgid=msgget(key,IPC_CREAT|0666))==EOF){perror("msgget");return -1;}//創建并運行一個線程pthread_t thread;if((thread=pthread_create(&thread,NULL,ltread,NULL))!=0){perror("pthread_create");return -1;}struct msgbuf wbuf;signal(SIGINT,SIG_IGN);while(1){memset(&wbuf,0,sizeof(wbuf));//初始化結構體wbuf.mtype=2;//確定消息編號printf("2號輸入:");fgets(wbuf.mtext,128,stdin);//直接讀取終端輸入,避免了scanf不吸收空格的影響msgsnd(msgid,&wbuf,strlen(wbuf.mtext),0);//將消息寫入消息隊列,以阻塞的形式}return 0; }