基于消息队列的C/S通信
来源:互联网 发布:href中调用javascript 编辑:程序博客网 时间:2024/06/06 03:48
程序示意图:
程序思路:
分别写客户端和服务端的函数,在主任务中创建两个client和一个server,考虑到实际情况,应该server的优先级高并且先用taskSpawn函数创建server任务。然后等待客户端获得服务端的应答,则删除队列,程序结束。为了演示client请求,server应答的过程,本次实验采取client发送时发送一个value,在创建任务时给定,每次请求时value加一,服务端获得value之后将该值加一,并根据客户端的id,返回给相应的响应队列。Client函数中首先根据请求队列的大小发送数据,然后开始等待接收响应队列的返回结果。Server函数中等待请求队列不为空,获得请求并返回给对应的响应队列。
关键代码:
- main.h
- #ifndef MAIN_H_INCLUDED
- #define MAIN_H_INCLUDED
- #include "vxWorks.h"
- #include "semLib.h"
- #include "taskLib.h"
- #include "msgQLib.h"
- #include "sysLib.h"
- #include "stdio.h"
- #define CLIENT_TASK_PRI 99
- #define SERVER_TASK_PRI 98
- #define TASK_STACK_SIZE 5000
- struct msg
- {
- int id;
- int value;
- };
- LOCAL MSG_Q_ID requestQId;
- LOCAL MSG_Q_ID response1QId;
- LOCAL MSG_Q_ID response2QId;
- LOCAL BOOL notDone;
- LOCAL int numMsg = 3;
- LOCAL STATUS clientTask (int cid, int value);
- LOCAL STATUS serverTask(void);
- #endif // MAIN_H_INCLUDED
- #include "main.h"
- STATUS clientTask(int cid, int value)
- {
- int i, j, k;
- struct msg request_msg, response_msg;
- printf ("clientTask started: cid = %d\n", cid);
- for(i=0; i<numMsg; i++)
- {
- request_msg.id = cid;
- request_msg.value = value+i;
- /* semTake(request_semMutex, WAIT_FOREVER);*/
- if (( msgQSend (requestQId, (char *) &request_msg, sizeof (request_msg),
- WAIT_FOREVER, MSG_PRI_NORMAL)) == ERROR)
- {
- perror ("Error in sending the message to request queue\n");
- return (ERROR);
- }
- else
- {
- printf ("clientTask: cid = %d, value = %d \n",
- cid, value+i);
- }
- /*semGive(request_semMutex);*/
- }
- /*接收数据从responseQ*/
- if(1 == cid)
- {
- for(j=0; j<numMsg; j++)
- {
- /* semTake(response1_semMutex, WAIT_FOREVER);*/
- if (( msgQReceive (response1QId, (char *) &response_msg,
- sizeof (response_msg), WAIT_FOREVER)) == ERROR)
- {
- perror ("Error in receiving the response1 message\n");
- return (ERROR);
- }
- else
- {
- printf ("clientTask: get msg of value %d from cid = %d\n",
- response_msg.value, response_msg.id);
- }
- /* semGive(response1_semMutex);*/
- }
- }
- else if(2 == cid)
- {
- for(k=0; k<numMsg; k++)
- {
- /* semTake(response2_semMutex, WAIT_FOREVER);*/
- if (( msgQReceive (response2QId, (char *) &response_msg,
- sizeof (response_msg), WAIT_FOREVER)) == ERROR)
- {
- perror ("Error in receiving the response2 message\n");
- return (ERROR);
- }
- else
- {
- printf ("clientTask: get msg of value %d from cid = %d\n",
- response_msg.value, response_msg.id);
- }
- /* semGive(response2_semMutex);*/
- }
- }
- else
- {
- printf("clientTask: cid error!\n");
- }
- notDone = FALSE;
- return (OK);
- }
- STATUS serverTask(void)
- {
- int i;
- struct msg response_msg ;
- printf ("\nserverTask Started \n");
- for(i=0; i<numMsg*2; i++)
- {
- /* semTake(request_semMutex, WAIT_FOREVER);*/
- if (( msgQReceive (requestQId, (char *) &response_msg,
- sizeof (response_msg), WAIT_FOREVER)) == ERROR)
- {
- perror ("Error in receiving the message\n");
- return (ERROR);
- }
- else
- {
- printf ("serverTask: get msg of value %d from cid = %d\n",
- response_msg.value, response_msg.id);
- }
- /*semGive(request_semMutex);*/
- /*将获得的value加一后,根据cid发给相应的应答序列*/
- response_msg.value += 1;
- if(response_msg.id==1)
- {
- /*semTake(response1_semMutex, WAIT_FOREVER);*/
- if (( msgQSend (response1QId, (char *) &response_msg, sizeof (response_msg),
- WAIT_FOREVER, MSG_PRI_NORMAL)) == ERROR)
- {
- perror ("Error in sending the message to response1 queue\n");
- return (ERROR);
- }
- else
- {
- printf ("serverTask sending to response Q1: value = %d \n",
- response_msg.value);
- }
- /*semGive(response1_semMutex);*/
- }
- else if(response_msg.id==2)
- {
- /*semTake(response2_semMutex, WAIT_FOREVER);*/
- if (( msgQSend (response2QId, (char *) &response_msg, sizeof (response_msg),
- WAIT_FOREVER, MSG_PRI_NORMAL)) == ERROR)
- {
- perror ("Error in sending the message to response2 queue\n");
- return (ERROR);
- }
- else
- {
- printf ("serverTask sending to response Q2: value = %d \n",
- response_msg.value);
- }
- /*semGive(response2_semMutex);*/
- }
- else
- {
- printf("error in response_msg, the id = %d\n", response_msg.id);
- }
- }
- return (OK);
- }
- STATUS main()
- {
- notDone = TRUE;
- /* request_semMutex = semBCreate(SEM_Q_FIFO, SEM_FULL);
- response1_semMutex = semBCreate(SEM_Q_FIFO, SEM_FULL);
- response2_semMutex = semBCreate(SEM_Q_FIFO, SEM_FULL);*/
- if ((requestQId = msgQCreate(numMsg*2, sizeof (struct msg), MSG_Q_FIFO)) == NULL)
- {
- perror ("Error in creating requestQ");
- return (ERROR);
- }
- if ((response1QId = msgQCreate(numMsg, sizeof (struct msg), MSG_Q_FIFO)) == NULL)
- {
- perror ("Error in creating response1Q");
- return (ERROR);
- }
- if ((response2QId = msgQCreate(numMsg, sizeof (struct msg), MSG_Q_FIFO)) == NULL)
- {
- perror ("Error in creating response2Q");
- return (ERROR);
- }
- if (taskSpawn (" tserverTask ", SERVER_TASK_PRI, 0, TASK_STACK_SIZE,
- (FUNCPTR) serverTask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR)
- {
- perror ("serverTask: Error in spawning serverTask");
- return (ERROR);
- }
- if (taskSpawn (" tclientTask ", CLIENT_TASK_PRI, 0, TASK_STACK_SIZE,
- (FUNCPTR) clientTask, 1, 10, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR)
- {
- perror ("clientTask: Error in spawning clientTask1");
- return (ERROR);
- }
- if (taskSpawn (" tclientTask ", CLIENT_TASK_PRI, 0, TASK_STACK_SIZE,
- (FUNCPTR) clientTask, 2, 10, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR)
- {
- perror ("clientTask: Error in spawning clientTask2");
- return (ERROR);
- }
- while (notDone)
- {
- taskDelay (sysClkRateGet ());
- }
- if (msgQDelete(requestQId) == ERROR || msgQDelete(response1QId) == ERROR ||
- msgQDelete(response2QId) == ERROR)
- {
- perror ("Error in deleting msgQs");
- return (ERROR);
- }
- return (OK);
- }
实验结果:
可以看出,首先进入了server任务,然后进入client任务,client发送给请求队列消息后,服务端立刻获得value值,因为server优先级高,所以打印发送信息也是在server阻塞后打印的,并且能够看出serverl立刻向相应的响应队列发送了消息,此时value的值比client发过来的值多一,符合程序的设计,后来也是如此。直到client1的请求都被响应了,client1从自己的响应队列中得到加一后的值,之后client2也同理。
下面是windview演示结果:
第一幅能看出t1即主任务创建了三个任务,然后切换到Server,但是server被阻塞,因为请求队列为空,又切换到client1,当client1有请求之后再切换到server给予响应,依次进行,client2也是如此。下图是过了一段时间的截图,因为主程序一直在等待客户端接收到响应队列的消息,结束之后能从下图看出删除了请求队列和响应队列1,响应队列2,程序结束。
遇到问题:
1、 C语言的单行注释“//”不能使用,编译不能通过。
2、 刚开始使用二进制信号量控制队列只能有一个任务在发送或接受,造成死锁。发送之前将请求队列take,然后发送,由于server优先级高,此时还没有来得及释放信号量就切换到server任务,server接收请求队列获取不到信号量,造成一直等待的死锁局面。
3、 刚开始没有考虑实际情况,先创建了client1,client2,并且优先级设定为一致,而事实上应该先启动服务器在允许客户端请求,故更改顺序,先创建server任务。
4、用windview观察的时候要选择task state transition,刚开始使用默认的context switch观察不到想要的结果。之后观察成功,鼠标悬停就能看到相关的信息,非常方便。
- 基于消息队列的C/S通信
- 基于消息队列的C/S通信
- 实现基于VxWorks的消息队列通信机制的C/S通信
- VxWorks中基于消息队列实现C/S通信
- Linux c 基于内存的进程通信—共享内存、共享队列(消息队列)
- 消息队列的通信
- C 消息队列实现通信
- linux进程间的通信(C): 消息队列
- Linux——基于共享内存 消息队列和基于Socket的进程间的通信
- 基于socket通信的c/s模式开发
- 基于TCP协议的简易C/S通信
- linux C-(进程间通信 消息队列)
- C语言消息队列通信函数描述
- 基于redis的消息队列
- 基于Java的消息队列
- 【C语言】【unix c】两个进程通过消息队列实现进程间的通信
- 基于socket通信的,利用MFC实现TCP通信的C/S架构程序
- Linux消息队列进程通信的介绍
- Suneast & Yayamao(2062)
- Oracle 11g安装问题总结
- PageAdmin CMS关键词链接的使用方法
- 恣意玩耍荒唐青睐新天龙1整年燃情起始
- 懒加载
- 基于消息队列的C/S通信
- org.apache.hadoop.io
- android中的ellipsize
- 第八周 项目2-Time中的运算符重载
- [前端] 倒计时
- linux-压缩解压命令
- shell截取字符串的方法
- Java JNI (Java和C++互传ArrayList泛型对象参数)
- Android:ListView中嵌入GridView,处理点击事件的冲突