程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> C:TLV消息編碼及常用操作

C:TLV消息編碼及常用操作

編輯:關於C

/*
1、TLV簡介:
在通信系統中,兩個設備之前必然存在消息交互,消息的格式也存在各種編碼類型,
本文僅描述TLV編碼的消息格式。Type-length-value(TLV)格式中T、L的長度固定,
通常為1-8個4個字節,V的長度不固定,由L的值表示,V的內容也可以嵌套子TLV格式。
舉例:假設消息按大端模式存放,T占4個字節,L占2個字節,下面的消息:
 unsigned char pMsg[] = {0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01,0x01,0x01, 0x01}
 T = {0x09, 0x00, 0x00, 0x00},值為9。
 L = {0x04, 0x00},值為4。
 V = {0x01,0x01,0x01, 0x01} ,長度為4,每個字節的值均為1。
2、代碼實現:a、按T的值由小到大排序一個消息(假定消息中不存在T相同的信元);
             b、在兩個消息中查找相同的信元(T、L、V)均相同,並輸出信元個數。
       
作者:Socrates
日期:2014-08-05
*/

#include "stdafx.h"
#include 
#include 

#define TLV_T_LEN (4)
#define TLV_L_LEN (2)

/*錯誤碼*/
enum _RetCode
{
    ERR = -1, /*失敗*/
    OK = 0    /*成功*/
}RETCODE;

/*信元TLV結構*/
typedef struct _stIE 
{
    unsigned int ulTag;    /*T*/
    unsigned short usLen;  /*L*/
    unsigned char *pValue; /*V*/
}IE;

/*消息鏈表*/
typedef struct _stMsg 
{
    IE ie;
    struct _stMsg *pNext;
}Msg;

/*
功能:創建鏈表
*/
int CreateMsgList(Msg *&pList)
{
    pList = (Msg *)malloc(sizeof(Msg));
    if (NULL == pList)
    {
        return ERR;
    }
    memset(&(pList->ie), 0, sizeof(IE));
    pList->pNext = NULL;

    return OK;
}

/*
功能:銷毀鏈表
*/
void DestoryMsgList(Msg *pList)
{
    if (NULL == pList)
    {
        return;
    }
    
    Msg *p = pList;
    while(NULL != p)
    {
        p = p->pNext;
        free(pList);
        pList = p;
    }  
    free(pList);
    pList = NULL;
    return;
}

/*
功能:向消息鏈表中插入信元,並保持按Tag遞增
*/
int InsertIEToMsgList(Msg *pMsgList, const IE *pIE)
{
    if ((NULL == pMsgList)
        || (NULL == pIE))
    {
        return ERR;
    }

    /*鏈表銷毀時釋放*/
    Msg *pInsertMsg = (Msg *)malloc(sizeof(Msg));
    if (NULL == pInsertMsg)
    {
        return ERR;
    }

    /*創建鏈表結點*/
    memcpy(&(pInsertMsg->ie), pIE, sizeof(IE));
    pInsertMsg->pNext = NULL;

    /*按Tag遞增插入結點,保持鏈表有序,不帶頭結點*/
    Msg *p = pMsgList;
    while(NULL != p->pNext)
    {
        if ((p->pNext->ie.ulTag) > (pIE->ulTag))
        {
            break;
        }
        p = p->pNext;
    }

    pInsertMsg->pNext = p->pNext;
    p->pNext = pInsertMsg;
    
    return OK;
}

/*
功能:獲取指定消息中的第一個信元
*/
IE *GetIEFromMsg(const unsigned char *pInMsg)
{
    if (NULL == pInMsg)
    {
        return NULL;
    }

    /*鏈表銷毀時釋放*/
    IE *pIE = (IE *)malloc(sizeof(IE));
    if (NULL == pIE)
    {
        return NULL;
    }
    memset(pIE, 0, sizeof(IE));
    
    pIE->ulTag = *(unsigned int *)pInMsg;
    pIE->usLen = *(unsigned short *)(pInMsg + TLV_T_LEN);
    pIE->pValue = (unsigned char *)(pInMsg + TLV_T_LEN + TLV_L_LEN);

    return pIE;
}

/*
功能:構造有序消息鏈表
*/
int CreateSortMsgList(unsigned char *pInMsg, unsigned int ulMsgLen, Msg *&pOutMsgList)
{

    if ((NULL == pInMsg)
        ||(0 == ulMsgLen))
    {
        return ERR;
    }

    /*建立鏈表*/
    if (ERR == CreateMsgList(pOutMsgList))
    {
        return ERR;
    }

    unsigned int iTmpMsgLen = 0;
    IE *pIE = NULL;

    /*遍歷消息,注意獲取信元並插入消息鏈表*/
    while(iTmpMsgLen < ulMsgLen)
    {
        pIE = GetIEFromMsg(pInMsg);
        if (NULL == pIE)
        {
            return ERR;
        }

        if(ERR == InsertIEToMsgList(pOutMsgList, pIE))
        {
            return ERR;
        }

        pInMsg += (TLV_T_LEN + TLV_L_LEN + pIE->usLen);
        iTmpMsgLen += (TLV_T_LEN + TLV_L_LEN + pIE->usLen);
    }    

    return OK;  
}

/*
功能:消息排序
*/
int Sort(unsigned char *pInMsg, unsigned int ulMsgLen, unsigned char *pOutMsg)
{
    if ((NULL == pInMsg)
        || (NULL == pOutMsg)
        || (0 == ulMsgLen))
    {
        return ERR;
    }

    /*建立有序消息鏈表*/
    unsigned char *pTmp = pOutMsg;
    Msg *pMsgList = NULL;
    if (ERR == CreateSortMsgList(pInMsg, ulMsgLen, pMsgList))
    {
        DestoryMsgList(pMsgList);
        return ERR;
    }

    /*輸出排序後的消息*/
    Msg *pList = pMsgList->pNext;
    while(NULL != pList)
    {
        memcpy(pTmp, &(pList->ie), TLV_T_LEN + TLV_L_LEN);
        memcpy(pTmp + TLV_T_LEN + TLV_L_LEN, pList->ie.pValue, pList->ie.usLen);
        pTmp += (TLV_T_LEN + TLV_L_LEN + pList->ie.usLen);
        pList = pList->pNext;
    }

    DestoryMsgList(pMsgList);
    return OK;
}

/*
功能:比較兩個信元是否相同
*/
int IsSameIE(IE *pIE1, IE *pIE2)
{
    if ((NULL == pIE1)
        || (NULL == pIE2))
    {
        return ERR; 
    }

    if ((pIE1->ulTag == pIE2->ulTag)
        && (pIE1->usLen == pIE2->usLen)
        && (0 == memcmp(pIE1->pValue, pIE2->pValue, pIE1->usLen)))
    {
        return OK;
    }
        
    return ERR;
}

/*
功能:比較兩個消息,並輸出相同信元個數
*/
int CompareMsg(unsigned char *pMsg1, 
               unsigned int ulMsgLen1, 
               unsigned char *pMsg2,
               unsigned int ulMsgLen2,
               unsigned int *ulSameNum)

{
    /*創建有序消息鏈表1*/
    Msg *pMsgList1 = NULL;
    if (ERR == CreateSortMsgList(pMsg1, ulMsgLen1, pMsgList1))
    {
        DestoryMsgList(pMsgList1);
        return ERR;
    }

    /*創建有序消息鏈表2*/
    Msg *pMsgList2 = NULL;
    if (ERR == CreateSortMsgList(pMsg2, ulMsgLen2, pMsgList2))
    {
        DestoryMsgList(pMsgList1);
        DestoryMsgList(pMsgList2);
        return ERR;
    }

    Msg *p = pMsgList1->pNext;
    Msg *q = NULL;
    unsigned int iCount = 0;

    /*比較消息*/
    while(NULL != p)
    {
        q = pMsgList2->pNext;
        while(NULL != q)
        {
            if (OK == IsSameIE(&(p->ie), &(q->ie)))
            {
                iCount++;
            }
     
            q = q->pNext;
        }
        p = p->pNext;
    }

    DestoryMsgList(pMsgList1);
    DestoryMsgList(pMsgList2);
    
    *ulSameNum = iCount;

    return OK;

}


int main(int argc, char* argv[])
{
    unsigned char pMsg[] = {0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01,0x01,0x01, 0x01,
                            0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02,0x02,0x02, 0x02, 0x02, 0x02, 0x02,
                            0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03,0x03,0x03, 0x03, 0x03,
                            0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01,0x01,0x01, 0x01,
                            0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x08,0x08,
                            0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x09,0x09,0x09, 0x09};

    unsigned char pMsg2[] = {0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01,0x01,0x01, 0x01,
                            0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02,0x02,0x02, 0x02, 0x02, 0x02, 0x02,
                            0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03,0x03,0x03, 0x03, 0x03,
                            0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01,0x01,0x01, 0x01,
                            0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x08,0x08,
                            0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x09,0x09,0x09, 0x09};
    int iLen = sizeof(pMsg) / sizeof(pMsg[0]);
    for (int i = 0; i < iLen; i++)
    {
        printf("0x%x,", pMsg[i]);
    }
    printf("\n\n");

    unsigned char *pSortMsg = (unsigned char *)malloc(iLen);
    if (NULL == pSortMsg)
    {
        return ERR;
    }

    if (ERR != Sort(pMsg, iLen, pSortMsg))
    {
        for (int i = 0; i < iLen; i++)
        {
            printf("0x%x,", pSortMsg[i]);
        }
    }

    int iLen2 = sizeof(pMsg2) / sizeof(pMsg2[0]);
    unsigned int iSameNum = 0;
    
    if (ERR != CompareMsg(pMsg, iLen, pMsg2, iLen2, &iSameNum))
    {
        printf("\nSame Number is %d", iSameNum);
    }
    
    getchar();
    return 0;
}



  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved