基于消息队列的C/S通信

程序示意图:



程序思路:

         分别写客户端和服务端的函数,在主任务中创建两个client和一个server,考虑到实际情况,应该server的优先级高并且先用taskSpawn函数创建server任务。然后等待客户端获得服务端的应答,则删除队列,程序结束。为了演示client请求,server应答的过程,本次实验采取client发送时发送一个value,在创建任务时给定,每次请求时value加一,服务端获得value之后将该值加一,并根据客户端的id,返回给相应的响应队列。Client函数中首先根据请求队列的大小发送数据,然后开始等待接收响应队列的返回结果。Server函数中等待请求队列不为空,获得请求并返回给对应的响应队列。


关键代码:

[cpp]  view plain copy
  1. main.h  
  2. #ifndef MAIN_H_INCLUDED  
  3. #define MAIN_H_INCLUDED  
  4. #include "vxWorks.h"  
  5. #include "semLib.h"  
  6. #include "taskLib.h"  
  7. #include "msgQLib.h"  
  8. #include "sysLib.h"  
  9. #include "stdio.h"  
  10. #define  CLIENT_TASK_PRI          99  
  11. #define  SERVER_TASK_PRI          98  
  12. #define  TASK_STACK_SIZE          5000  
  13. struct msg  
  14. {  
  15.     int id;  
  16.     int value;  
  17. };  
  18. LOCAL MSG_Q_ID requestQId;  
  19. LOCAL MSG_Q_ID response1QId;  
  20. LOCAL MSG_Q_ID response2QId;  
  21.   
  22. LOCAL BOOL notDone;  
  23. LOCAL int numMsg = 3;  
  24. LOCAL STATUS clientTask (int cid, int value);  
  25. LOCAL STATUS serverTask(void);  
  26. #endif // MAIN_H_INCLUDED  

[cpp]  view plain copy
  1. #include "main.h"  
  2. STATUS clientTask(int cid, int value)  
  3. {  
  4.     int i, j, k;  
  5.     struct msg request_msg, response_msg;  
  6.     printf ("clientTask started: cid = %d\n", cid);  
  7.     for(i=0; i<numMsg; i++)  
  8.     {  
  9.         request_msg.id = cid;  
  10.         request_msg.value = value+i;  
  11.        /* semTake(request_semMutex, WAIT_FOREVER);*/  
  12.         if (( msgQSend (requestQId, (char *) &request_msg, sizeof (request_msg),  
  13.                         WAIT_FOREVER,  MSG_PRI_NORMAL)) == ERROR)  
  14.         {  
  15.             perror ("Error in sending the message to request queue\n");  
  16.             return (ERROR);  
  17.         }  
  18.         else  
  19.         {  
  20.             printf ("clientTask: cid = %d, value = %d \n",  
  21.                     cid, value+i);  
  22.         }  
  23.         /*semGive(request_semMutex);*/  
  24.     }  
  25. /*接收数据从responseQ*/  
  26.     if(1 ==  cid)  
  27.     {  
  28.         for(j=0; j<numMsg; j++)  
  29.         {  
  30.            /* semTake(response1_semMutex, WAIT_FOREVER);*/  
  31.             if (( msgQReceive (response1QId, (char *) &response_msg,  
  32.                                sizeof (response_msg), WAIT_FOREVER)) == ERROR)  
  33.             {  
  34.                 perror ("Error in receiving the response1 message\n");  
  35.                 return (ERROR);  
  36.             }  
  37.             else  
  38.             {  
  39.                 printf ("clientTask: get msg of value %d from cid = %d\n",  
  40.                         response_msg.value, response_msg.id);  
  41.             }  
  42.         /*    semGive(response1_semMutex);*/  
  43.         }  
  44.   
  45.     }  
  46.     else if(2 == cid)  
  47.     {  
  48.         for(k=0; k<numMsg; k++)  
  49.         {  
  50.        /*     semTake(response2_semMutex, WAIT_FOREVER);*/  
  51.             if (( msgQReceive (response2QId, (char *) &response_msg,  
  52.                                sizeof (response_msg), WAIT_FOREVER)) == ERROR)  
  53.             {  
  54.                 perror ("Error in receiving the response2 message\n");  
  55.                 return (ERROR);  
  56.             }  
  57.             else  
  58.             {  
  59.                 printf ("clientTask: get msg of value %d from cid = %d\n",  
  60.                         response_msg.value, response_msg.id);  
  61.             }  
  62.          /*   semGive(response2_semMutex);*/  
  63.         }  
  64.   
  65.     }  
  66.     else  
  67.     {  
  68.         printf("clientTask: cid error!\n");  
  69.     }  
  70.     notDone = FALSE;  
  71.     return (OK);  
  72. }  
  73.   
  74. STATUS serverTask(void)  
  75. {  
  76.     int i;  
  77.     struct msg response_msg ;  
  78.     printf ("\nserverTask Started \n");  
  79.     for(i=0; i<numMsg*2; i++)  
  80.     {  
  81.     /*  semTake(request_semMutex, WAIT_FOREVER);*/  
  82.         if (( msgQReceive (requestQId, (char *) &response_msg,  
  83.                        sizeof (response_msg), WAIT_FOREVER)) == ERROR)  
  84.         {  
  85.             perror ("Error in receiving the message\n");  
  86.             return (ERROR);  
  87.         }  
  88.         else  
  89.         {  
  90.             printf ("serverTask: get msg of value %d from cid = %d\n",  
  91.                     response_msg.value, response_msg.id);  
  92.         }  
  93.         /*semGive(request_semMutex);*/  
  94.         /*将获得的value加一后,根据cid发给相应的应答序列*/  
  95.         response_msg.value += 1;  
  96.         if(response_msg.id==1)  
  97.         {  
  98.             /*semTake(response1_semMutex, WAIT_FOREVER);*/  
  99.             if (( msgQSend (response1QId, (char *) &response_msg, sizeof (response_msg),  
  100.                             WAIT_FOREVER,  MSG_PRI_NORMAL)) == ERROR)  
  101.             {  
  102.                 perror ("Error in sending the message to response1 queue\n");  
  103.                 return (ERROR);  
  104.             }  
  105.             else  
  106.             {  
  107.                 printf ("serverTask sending to response Q1: value = %d \n",  
  108.                         response_msg.value);  
  109.             }  
  110.             /*semGive(response1_semMutex);*/  
  111.         }  
  112.         else if(response_msg.id==2)  
  113.         {  
  114.             /*semTake(response2_semMutex, WAIT_FOREVER);*/  
  115.             if (( msgQSend (response2QId, (char *) &response_msg, sizeof (response_msg),  
  116.                             WAIT_FOREVER,  MSG_PRI_NORMAL)) == ERROR)  
  117.             {  
  118.                 perror ("Error in sending the message to response2 queue\n");  
  119.                 return (ERROR);  
  120.             }  
  121.             else  
  122.             {  
  123.                 printf ("serverTask sending to response Q2: value = %d \n",  
  124.                         response_msg.value);  
  125.             }  
  126.             /*semGive(response2_semMutex);*/  
  127.         }  
  128.         else  
  129.         {  
  130.             printf("error in response_msg, the id = %d\n", response_msg.id);  
  131.         }  
  132.     }      
  133.     return (OK);  
  134. }  
  135.   
  136. STATUS main()  
  137. {  
  138.     notDone = TRUE;  
  139.    /* request_semMutex = semBCreate(SEM_Q_FIFO, SEM_FULL); 
  140.     response1_semMutex = semBCreate(SEM_Q_FIFO, SEM_FULL); 
  141.     response2_semMutex = semBCreate(SEM_Q_FIFO, SEM_FULL);*/  
  142.     if ((requestQId = msgQCreate(numMsg*2, sizeof (struct msg), MSG_Q_FIFO)) == NULL)  
  143.     {  
  144.         perror ("Error in creating requestQ");  
  145.         return (ERROR);  
  146.     }  
  147.     if ((response1QId = msgQCreate(numMsg, sizeof (struct msg), MSG_Q_FIFO)) == NULL)  
  148.     {  
  149.         perror ("Error in creating response1Q");  
  150.         return (ERROR);  
  151.     }  
  152.     if ((response2QId = msgQCreate(numMsg, sizeof (struct msg), MSG_Q_FIFO)) == NULL)  
  153.     {  
  154.         perror ("Error in creating response2Q");  
  155.         return (ERROR);  
  156.     }  
  157.     if (taskSpawn (" tserverTask ", SERVER_TASK_PRI, 0, TASK_STACK_SIZE,  
  158.                    (FUNCPTR) serverTask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR)  
  159.     {  
  160.         perror ("serverTask: Error in spawning serverTask");  
  161.         return (ERROR);  
  162.     }  
  163.     if (taskSpawn (" tclientTask ", CLIENT_TASK_PRI, 0, TASK_STACK_SIZE,  
  164.                    (FUNCPTR) clientTask, 1, 10, 0, 0, 0, 0, 0, 0, 0, 0)  == ERROR)  
  165.     {  
  166.         perror ("clientTask: Error in spawning clientTask1");  
  167.         return (ERROR);  
  168.     }  
  169.     if (taskSpawn (" tclientTask ", CLIENT_TASK_PRI, 0, TASK_STACK_SIZE,  
  170.                    (FUNCPTR) clientTask, 2, 10, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR)  
  171.     {  
  172.         perror ("clientTask: Error in spawning clientTask2");  
  173.         return (ERROR);  
  174.     }  
  175.       
  176.     while (notDone)  
  177.     {  
  178.         taskDelay (sysClkRateGet ());       
  179.     }  
  180.         if (msgQDelete(requestQId) == ERROR || msgQDelete(response1QId) == ERROR ||  
  181.            msgQDelete(response2QId) == ERROR)  
  182.         {  
  183.             perror ("Error in deleting msgQs");  
  184.             return (ERROR);  
  185.         }  
  186.     return (OK);  
  187. }  

实验结果:


    可以看出,首先进入了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观察不到想要的结果。之后观察成功,鼠标悬停就能看到相关的信息,非常方便。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值