揚州大學的操作系統課設,一道很好的題目,功能是用消息隊列實現客戶機與服務器的連接,兩個客戶機發送自己的私有消息隊列id給客戶機,客戶機收到之後連接這兩個客戶機實現通信。
有問題請留言。
代碼已經上傳到Github:點這裏 歡迎Star關注後續更新
要求
學習Linux的進程間通信機制,使用消息隊列通信實現兩個客戶機和一個服務器之間的通信。具體要求:
1.創建兩個客戶進程,以及一個服務進程。
2.在每個客戶進程中創建一個用於接收消息的私有消息隊列。並將消息隊列的id號發送給服務器進行“註冊”。
3.在服務器端創建一個公共消息隊列,用於接收客戶機發來的私有消息隊列id號,服務器記錄下兩個客戶機的消息隊列id號後,負責將id號傳遞給對方客戶機(如A客戶機的id號傳給B客戶機,B客戶機的id號傳給A客戶機),以便實現兩客戶機的通信。
4.每個客戶機從自己的私有隊列接收服務器發來的另一客戶機私有消息隊列id號,從而可以通過對方的消息隊列id號,向對方發送消息,客戶機之間通過各自的私有消息隊列接收消息。客戶機設置兩個線程,一個負責發送消息,一個負責接收消息。從而實現兩客戶機的通信。
思路
服務端:使用約定的key_t創建公共消息隊列,使用兩個msgrcv函數語句等待獲取兩個私有消息隊列的id,獲取之後分別發送給另外一方。
因爲結構必須被定義爲一個類型碼和一個數組,所以要注意字符串和int的轉換。
客戶端:創建私有消息隊列連接公共消息隊列,創建兩個線程,一個用於消息發送,一個用於消息接收。
注意消息隊列傳參時候的指針引用和解引用。
代碼
server.c
#include <sys/msg.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct msgbuf {
long mType;
char mText[50];
};
int main() {
char txtBuf[50];
int qId,pid_1,pid_2;
key_t key;
struct msgbuf msg, buf_1,buf_2;
struct msqid_ds msgCtlBuf;
if ((key = ftok("/tmp", 'C')) == -1) {
perror("server: ftok failed:");
exit(1);
}
printf("server: System V IPC key = %u\n", key);
if ((qId = msgget(key, IPC_CREAT | 0666)) == -1) {
perror("server: Failed to create message queue:");
exit(2);
}
printf("server: Message queue id = %u\n", qId);
if (msgrcv(qId, &buf_1, sizeof msg.mText, 1, 0) == -1)
perror("client: msgrcv failed:");
else{
printf("client: Message received = %s\n", buf_1.mText);
sscanf(buf_1.mText,"privateId_1 = %d\n",&pid_1);
}
if (msgrcv(qId, &buf_2, sizeof msg.mText, 1, 0) == -1)
perror("client: msgrcv failed:");
else{
printf("client: Message received = %s\n", buf_2.mText);
sscanf(buf_2.mText,"privateId_2 = %d\n",&pid_2);
}
printf("server: waiting...\n");
printf("%d,%d\n",pid_1,pid_2);
if (msgsnd(pid_1, &buf_2, sizeof msg.mText, 0) == -1) {
perror("server: msgsnd failed:");
exit(3);
}
if (msgsnd(pid_2, &buf_1, sizeof msg.mText, 0) == -1) {
perror("server: msgsnd failed:");
exit(3);
}
printf("server: Message sent successfully\n");
sleep(15);
printf("server: done waiting. removing message queue...\n");
if (msgctl(qId, IPC_RMID, &msgCtlBuf) == -1) {
perror("server: msgctl failed:");
exit(4);
}
printf("server: Message queue removed OK\n");
}
client.c
#include <sys/msg.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include<stdlib.h>
struct msgbuf {
long mType;
char mText[50];
};
void *_write(void *arg){
struct msgbuf msg;
while(1){
msg.mType = 1;
fgets(msg.mText,50,stdin);
if (msgsnd(*(int*)arg, &msg, sizeof msg.mText, 0) == -1) {
perror("client: msgsnd failed:");
exit(3);
}
}
}
void *_read(void *arg){
struct msgbuf msg;
while(1)
{
int res = msgrcv(*(int*)arg,&msg,sizeof msg.mText,1,0);
if(res==-1){
perror("client: somthing wrong");
exit(-3);
}
printf("%s",msg.mText);
}
}
int main() {
char txtBuf[50];
int qId,privateId,anotherId;
key_t key;
struct msgbuf msg, buf;
struct msqid_ds msgCtlBuf;
pthread_t id1,id2;
if ((key = ftok("/tmp", 'C')) == -1) {
perror("client: ftok failed:");
exit(1);
}
printf("client: System V IPC key = %u\n", key);
if ((qId = msgget(key, IPC_CREAT | 0666)) == -1) {
perror("client: Failed to create message queue:");
exit(2);
}
if ((privateId = msgget(IPC_PRIVATE, IPC_CREAT | 0666)) == -1) {
perror("client: Failed to create message queue:");
exit(2);
}
printf("client: Message queue id = %u\n", qId);
printf("privateId_1 = %u\n",privateId);
sprintf(txtBuf,"privateId_1 = %u\n",privateId);
strcpy(msg.mText, txtBuf);
msg.mType = 1;
if (msgsnd(qId, &msg, sizeof msg.mText, 0) == -1) {
perror("server: msgsnd failed:");
exit(3);
}
printf("client: Message sent successfully\n");
//
// attempt read again and block on queue waiting for server to IPC_RMID
if (msgrcv(privateId, &buf, sizeof msg.mText, 1, 0) == -1)
perror("client: msgrcv failed:");
else{
printf("client: Message received = %s\n", buf.mText);
sscanf(buf.mText,"privateId_2 = %d\n",&anotherId);
}
printf("connect success!");
int res1 = pthread_create(&id1,0,_write,&anotherId);
int res2 = pthread_create(&id2,0,_read,&privateId);
pthread_join(id1,0);
pthread_join(id2,0);
return 0;
}
client2.c
#include <sys/msg.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include<stdlib.h>
struct msgbuf {
long mType;
char mText[50];
};
void *_write(void *arg){
struct msgbuf msg;
while(1){
msg.mType = 1;
fgets(msg.mText,50,stdin);
if (msgsnd(*(int*)arg, &msg, sizeof msg.mText, 0) == -1) {
perror("client: msgsnd failed:");
exit(3);
}
}
}
void *_read(void *arg){
struct msgbuf msg;
while(1)
{
int res = msgrcv(*(int*)arg,&msg,sizeof msg.mText,1,0);
if(res==-1){
perror("client: somthing wrong");
exit(-3);
}
printf("%s",msg.mText);
}
}
int main() {
char txtBuf[50];
int qId,privateId,anotherId;
key_t key;
struct msgbuf msg, buf;
struct msqid_ds msgCtlBuf;
pthread_t id1,id2;
if ((key = ftok("/tmp", 'C')) == -1) {
perror("client: ftok failed:");
exit(1);
}
printf("client: System V IPC key = %u\n", key);
if ((qId = msgget(key, IPC_CREAT | 0666)) == -1) {
perror("client: Failed to create message queue:");
exit(2);
}
if ((privateId = msgget(IPC_PRIVATE, IPC_CREAT | 0666)) == -1) {
perror("client: Failed to create message queue:");
exit(2);
}
printf("client: Message queue id = %u\n", qId);
printf("privateId_2 = %u\n",privateId);
sprintf(txtBuf,"privateId_2 = %u\n",privateId);
strcpy(msg.mText, txtBuf);
msg.mType = 1;
if (msgsnd(qId, &msg, sizeof msg.mText, 0) == -1) {
perror("server: msgsnd failed:");
exit(3);
}
printf("client: Message sent successfully\n");
//
// attempt read again and block on queue waiting for server to IPC_RMID
//
if (msgrcv(privateId, &buf, sizeof msg.mText, 1, 0) == -1)
perror("client: msgrcv failed:");
else{
printf("client: Message received = %s\n", buf.mText);
sscanf(buf.mText,"privateId_1 = %d\n",&anotherId);
}
printf("connect success!");
int res1 = pthread_create(&id1,0,_write,&anotherId);
int res2 = pthread_create(&id2,0,_read,&privateId);
pthread_join(id1,0);
pthread_join(id2,0);
return 0;
}
運行截圖