课题六 - 消息队列实现客户机通信

某一本大学的操作系统课设,一道很好的题目,功能是用消息队列实现客户机与服务器的连接,两个客户机发送自己的私有消息队列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的转换。
客户端:创建私有消息队列连接公共消息队列,创建两个线程,一个用于消息发送,一个用于消息接收。
注意消息队列传参时候的指针引用和解引用。

流程图

补加流程图。
课题六 - 消息队列实现客户机通信_第1张图片
课题六 - 消息队列实现客户机通信_第2张图片

代码

server.c

#include 
#include 
#include 
#include 
#include 
#include 

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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include

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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include

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;


}

运行截图

课题六 - 消息队列实现客户机通信_第3张图片
课题六 - 消息队列实现客户机通信_第4张图片
课题六 - 消息队列实现客户机通信_第5张图片

你可能感兴趣的:(OS,某大学十二个os课设)