⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c04c_cs.c

📁 Tornado的源代码资源包
💻 C
字号:
/* C04c_CS.c P91 */

/* 头文件 */ 
#include "vxWorks.h" 
#include "msgQLib.h" 
 
/* 宏定义 */ 
#define  MAX_MSGS       (10)            /* 消息队列长度 */
#define  MAX_MSG_LEN    sizeof(MESSAGE) /* 消息队列中消息的最大长度 */
#define  STACK_SIZE     20000           /* 分配给每个任务的堆栈大小 */
#define  DELAY_TICKS    50              /* client发送消息的间隔时间 */
#define  NUM_CLIENT     2               /* 客户程序的个数 */

/* MESSAGE ID定义, 
 * 用于MESSAGE类型中mSendId、mRecvId两个字段
 */
#define  MID_CLIENT(id) (id)            /* id=0..(NUM_CLIENT – 1) */
#define  MID_SERVER     NUM_CLIENT      /* server的MESSAGE ID,
                                         * 为Client中最大的ID + 1
                                         */

/* 类型定义 */
typedef struct _MESSAGE 
{
    int   mSendId;                      /* 发送任务的MESSAGE ID */
    int   mRecvId;                      /* 接收任务的MESSAGE ID */
    int   mData;                        /* 消息中传递的数据 */
}MESSAGE;
 
/* 全局变量 */
int      tidServer;                     /* 任务ID定义 */
int      tidClient[NUM_CLIENT];
MSG_Q_ID msgQIdServer;                  /* 消息队列ID定义 */
MSG_Q_ID msgQIdClient[NUM_CLIENT];  

/* 函数声明 */
STATUS progStart(void);
STATUS server(void);
STATUS client(int id);
void   progStop(void);

/******************************************************************
*
* progStart - 启动实例程序
*
* 负责创建消息队列与任务,其中对于不同的客户任务,通过id参数来区别
*
* RETURNS: OK, ERROR
*/
STATUS progStart(void)
{
    int id; /* 用来区分不同的客户任务 */
    
    /* 创建消息队列 */ 
    msgQIdServer = msgQCreate(MAX_MSGS, MAX_MSG_LEN, MSG_Q_PRIORITY);
    if (msgQIdServer == NULL) 
    {
        return (ERROR); 
    }

    for (id = 0; id < NUM_CLIENT; id++)
    {
        msgQIdClient[id] = msgQCreate(MAX_MSGS, MAX_MSG_LEN, 
                                     MSG_Q_PRIORITY);
        if (msgQIdClient[id] == NULL) 
        {
            return (ERROR); 
        }
    }

    /* 创建任务 */
    tidServer  = taskSpawn("tServer", 220, 0, STACK_SIZE,
                           (FUNCPTR)server,0,0,0,0,0,0,0,0,0,0);

    for (id = 0; id < NUM_CLIENT; id++)
    {
        char tempName[20];

        sprintf(tempName, "tClient%d", id);
        tidClient[id] = taskSpawn(tempName, 200, 0, STACK_SIZE,
                                (FUNCPTR)client,id,0,0,0,0,0,0,0,0,0);
    }

    return (OK);
}

/******************************************************************
*
* server – 处理来自各个客户任务的消息
*
* 从消息队列接收消息,作简单地处理并回应ACK(应答)
*
* RETURNS: OK, ERROR
*/
STATUS server(void) 
{ 
    MESSAGE  rxMsg; /* 用于从消息队列中接收消息 */
    MESSAGE  txMsg; /* 用于向消息队列中发送消息 */

    /* 初始化txMsg,填写mSendId字段,
     * 表明消息的发送者是tServer
     */
    txMsg.mSendId = MID_SERVER;
    
    FOREVER
    {
        /* 从消息队列接收消息,当消息队列空时阻塞(Pend)等待 */
        if (msgQReceive(msgQIdServer, (char*)&rxMsg, MAX_MSG_LEN,
                        WAIT_FOREVER) == ERROR)
        {
            return (ERROR);
        }

        /* 处理消息 */

        /* 接收到的消息应该是发给自己的 */
        if (rxMsg.mRecvId != MID_SERVER)
        {
            return (ERROR);
        }

        /* 接收到的消息应该是某个tClient发出的 */
        if ((rxMsg.mSendId < MID_CLIENT(0)) ||
            (rxMsg.mSendId > MID_CLIENT(NUM_CLIENT - 1))
           ) 
        {
            return (ERROR);
        }
        
        /* 显示接收的数据 */
        printf("\ntServer: receive a date %d from tClient%d\n", 
               rxMsg.mData, rxMsg.mSendId);
        
        /* 根据接收到的消息配置回应消息txMsg*/
        txMsg.mRecvId = rxMsg.mSendId;
        txMsg.mData   = rxMsg.mData;

        /* 向对应的消息队列发送ACK(回应),
         * 当消息队列满时,阻塞(Pend)等待
         */ 
        if (msgQSend(msgQIdClient[rxMsg.mSendId], (char*)&txMsg, 
                     sizeof(MESSAGE), WAIT_FOREVER, 
                     MSG_PRI_NORMAL) == ERROR) 
        {
            return (ERROR); 
        }
    }

    return (OK);
}

/******************************************************************
*
* client – 向服务器任务发请求消息
*
* 周期性地生成数据,将数据发送给服务器任务,
* 并等待服务器任务将数据作为ACK回传回来
*
* RETURNS: OK, ERROR
*/
STATUS client
    (
    int id          /* 用来区分不同的客户任务,
                     * 创建的第一个客户任务的id取值为0,
                     * 其后创建的客户任务依次增加1
                     */
    ) 
{ 
    MESSAGE  rxMsg; /* 用于从消息队列中接收消息 */
    MESSAGE  txMsg; /* 用于向消息队列中发送消息 */ 

    /* 初始化txMsg,填写mSendId与mRecvId字段 */
    txMsg.mSendId = MID_CLIENT(id);
    txMsg.mRecvId = MID_SERVER;
    
    FOREVER
    {
        /* 得到一个随机的数据,用于发送 */
        txMsg.mData = rand();

        /* 向对应的服务器任务的消息队列发送消息,
         * 当消息队列满时,阻塞(Pend)等待
         */
        if (msgQSend(msgQIdServer, (char*)&txMsg, sizeof(MESSAGE), 
                     WAIT_FOREVER, MSG_PRI_NORMAL) == ERROR) 
        {
            return (ERROR); 
        }

        /* 显示发送的数据 */
        printf("\ntClient%d: transmit a data %d to tServer\n", 
                id, txMsg.mData);
        
        /* 接收服务器任务的ACK,设置timeout为20 ticks */ 
        if (msgQReceive(msgQIdClient[id], (char*)&rxMsg, 
                        MAX_MSG_LEN, 20) == ERROR) 
        {
            printf("\ntClient%d: wait ACK timeout!!!\n");
            continue;
        }
     
        /* 检验是否收到正确的ACK */
        printf("\ntClient%d: receive the ACK from tServer”, id);
        if (txMsg.mData == rxMsg.mData)
        {
            printf(", and data check OK!\n");
        }
        else
        {
            printf("\n, but data check ERROR!!!\n");
            printf("tx data(%d) != ACK data(%d)\n",
                    txMsg.mData, rxMsg.mData);
        }
        
        taskDelay(DELAY_TICKS + (txMsg.mData % DELAY_TICKS));
    } 

    return OK;
} 

/******************************************************************
*
* progStop - 停止实例程序
*
* 调用本函数来停止本实例程序,删除创建的任务并释放消息队列资源。
*
* RETURNS: N/A
*/
void progStop(void)
{
    int id;  /* 用来区分不同的客户任务 */
    
    for (id = 0; id < NUM_CLIENT; id++)
    {
        taskDelete(tidClient[id]);
    }
    taskDelete(tidServer);
    

    msgQDelete(msgQIdServer);
    for (id = 0; id < NUM_CLIENT; id++)
    {
        msgQDelete(msgQIdClient[id]);
    }
    
    printf("BYE!\n");

    return;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -