基於訊息佇列的C/S通訊

來源:互聯網
上載者:User
程式:



程式思路:

         分別寫用戶端和服務端的函數,在主任務中建立兩個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          5000struct 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觀察不到想要的結果。之後觀察成功,滑鼠移至上方就能看到相關的資訊,非常方便。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.