分享

使用队列实现C/S网络通信

 A_Geek 2013-09-17

程序示意图:



程序思路:

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


关键代码:

  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. LOCAL BOOL notDone;
  22. LOCAL int numMsg = 3;
  23. LOCAL STATUS clientTask (int cid, int value);
  24. LOCAL STATUS serverTask(void);
  25. #endif // MAIN_H_INCLUDED

  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. else if(2 == cid)
  46. {
  47. for(k=0; k<numMsg; k++)
  48. {
  49. /* semTake(response2_semMutex, WAIT_FOREVER);*/
  50. if (( msgQReceive (response2QId, (char *) &response_msg,
  51. sizeof (response_msg), WAIT_FOREVER)) == ERROR)
  52. {
  53. perror ("Error in receiving the response2 message\n");
  54. return (ERROR);
  55. }
  56. else
  57. {
  58. printf ("clientTask: get msg of value %d from cid = %d\n",
  59. response_msg.value, response_msg.id);
  60. }
  61. /* semGive(response2_semMutex);*/
  62. }
  63. }
  64. else
  65. {
  66. printf("clientTask: cid error!\n");
  67. }
  68. notDone = FALSE;
  69. return (OK);
  70. }
  71. STATUS serverTask(void)
  72. {
  73. int i;
  74. struct msg response_msg ;
  75. printf ("\nserverTask Started \n");
  76. for(i=0; i<numMsg*2; i++)
  77. {
  78. /* semTake(request_semMutex, WAIT_FOREVER);*/
  79. if (( msgQReceive (requestQId, (char *) &response_msg,
  80. sizeof (response_msg), WAIT_FOREVER)) == ERROR)
  81. {
  82. perror ("Error in receiving the message\n");
  83. return (ERROR);
  84. }
  85. else
  86. {
  87. printf ("serverTask: get msg of value %d from cid = %d\n",
  88. response_msg.value, response_msg.id);
  89. }
  90. /*semGive(request_semMutex);*/
  91. /*将获得的value加一后,根据cid发给相应的应答序列*/
  92. response_msg.value += 1;
  93. if(response_msg.id==1)
  94. {
  95. /*semTake(response1_semMutex, WAIT_FOREVER);*/
  96. if (( msgQSend (response1QId, (char *) &response_msg, sizeof (response_msg),
  97. WAIT_FOREVER, MSG_PRI_NORMAL)) == ERROR)
  98. {
  99. perror ("Error in sending the message to response1 queue\n");
  100. return (ERROR);
  101. }
  102. else
  103. {
  104. printf ("serverTask sending to response Q1: value = %d \n",
  105. response_msg.value);
  106. }
  107. /*semGive(response1_semMutex);*/
  108. }
  109. else if(response_msg.id==2)
  110. {
  111. /*semTake(response2_semMutex, WAIT_FOREVER);*/
  112. if (( msgQSend (response2QId, (char *) &response_msg, sizeof (response_msg),
  113. WAIT_FOREVER, MSG_PRI_NORMAL)) == ERROR)
  114. {
  115. perror ("Error in sending the message to response2 queue\n");
  116. return (ERROR);
  117. }
  118. else
  119. {
  120. printf ("serverTask sending to response Q2: value = %d \n",
  121. response_msg.value);
  122. }
  123. /*semGive(response2_semMutex);*/
  124. }
  125. else
  126. {
  127. printf("error in response_msg, the id = %d\n", response_msg.id);
  128. }
  129. }
  130. return (OK);
  131. }
  132. STATUS main()
  133. {
  134. notDone = TRUE;
  135. /* request_semMutex = semBCreate(SEM_Q_FIFO, SEM_FULL);
  136. response1_semMutex = semBCreate(SEM_Q_FIFO, SEM_FULL);
  137. response2_semMutex = semBCreate(SEM_Q_FIFO, SEM_FULL);*/
  138. if ((requestQId = msgQCreate(numMsg*2, sizeof (struct msg), MSG_Q_FIFO)) == NULL)
  139. {
  140. perror ("Error in creating requestQ");
  141. return (ERROR);
  142. }
  143. if ((response1QId = msgQCreate(numMsg, sizeof (struct msg), MSG_Q_FIFO)) == NULL)
  144. {
  145. perror ("Error in creating response1Q");
  146. return (ERROR);
  147. }
  148. if ((response2QId = msgQCreate(numMsg, sizeof (struct msg), MSG_Q_FIFO)) == NULL)
  149. {
  150. perror ("Error in creating response2Q");
  151. return (ERROR);
  152. }
  153. if (taskSpawn (" tserverTask ", SERVER_TASK_PRI, 0, TASK_STACK_SIZE,
  154. (FUNCPTR) serverTask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR)
  155. {
  156. perror ("serverTask: Error in spawning serverTask");
  157. return (ERROR);
  158. }
  159. if (taskSpawn (" tclientTask ", CLIENT_TASK_PRI, 0, TASK_STACK_SIZE,
  160. (FUNCPTR) clientTask, 1, 10, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR)
  161. {
  162. perror ("clientTask: Error in spawning clientTask1");
  163. return (ERROR);
  164. }
  165. if (taskSpawn (" tclientTask ", CLIENT_TASK_PRI, 0, TASK_STACK_SIZE,
  166. (FUNCPTR) clientTask, 2, 10, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR)
  167. {
  168. perror ("clientTask: Error in spawning clientTask2");
  169. return (ERROR);
  170. }
  171. while (notDone)
  172. {
  173. taskDelay (sysClkRateGet ());
  174. }
  175. if (msgQDelete(requestQId) == ERROR || msgQDelete(response1QId) == ERROR ||
  176. msgQDelete(response2QId) == ERROR)
  177. {
  178. perror ("Error in deleting msgQs");
  179. return (ERROR);
  180. }
  181. return (OK);
  182. }

实验结果:


可以看出,首先进入了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条评论

    发表

    请遵守用户 评论公约

    类似文章 更多