短信PDU解码 (转)

0891683108200505F0040D91683119930093F6000880015141652123044F60597D

第一段——短信中心码段

0891683108200505F0

1、短信息中心地址长度段

【SMSC-Length--短信中心号码长度】

首先看前两位“ 08”08* 2=16,即表示“08”后面的16位字符串为短信中心号码信息;

2、短信息中心号码类型

【Type-of-SMSC--短信中心号码类型(国际)】

再看后两位“91”,此“91”为短信息中心号码类型,91是TON/NPI。TON/NPI遵守International/E.164标准,指在号码前需加‘+’号;此外还可有其他数值,但91最常用;

3、短信息中心号码,即所使用的服务中心地址

【SMSC-Value--短信中心号码值】

再看“91”后面一段“683108200505F0”,将此段字符串的奇偶位换位得到“8613800250500F”此处“86”是国家代号,即中国国家代号,后面“13800250500F”中的“13800250500”即为短信中心号,后面的“F”为补充位,使得成为偶数位

第二段——手机号码段

040D91683119930093F6

1、【First-Octet,固定格式】

“ 04”—SMS_DELIVER的第一个8 位;

2、【Address-Length--源号码长度(13位)】

“0D”—发送方号码长度;“0D”转换成十进制即为“13”表示“发送方号码类型”后面13位为“发送方号码”,

3、

“91”—发送方号码类型(同第一段的“2”)

4、【Address-Value --源号码值(8613913900396)[13位]】

“683119930093F6”—发送方号码;将此段奇偶位换位得:“8613913900396F”

第三段——协议标识(TP-PID)与用户信息编码方式(TP-DCS)

0008

1、为协议标识

前两字符“00”,为协议标识(TP-Protocol-Identifier)。“00” 是普通 GSM 类型,表示点到点方式。

2、用户信息编码方式

再后面两个字符“08”,为用户信息编码方式(TP-DCS)数据编码方案DCS (DataCoding-Scheme),有关数值含义如下:

00:表示7比特,最多160个字符

04:表示为8比特,最多发140个字符

08:表示16比特,最多发70个汉字;

第四段——短信息发送的日期、时间与时区类型(DateTime Zone Type)【TP-SCTS:】

80015141652123

1、短信发送的日期

前六位数字800151,奇偶位换位得到“081015”,即表示 08年10月15日。

2、短信发送时间

接着六位数字416521 ,奇偶位换位得到“145621”,即表示14时56分21秒;

3、时区类型

接下来两位数字23,这即为时区类型。

第五段——用户数据长度与用户数据

044F60597D

1、用户数据长度

前两位“04”为用十六进制表示的用户数据长度,“04”转换成十进制为4,即其后面的8(8由4*2=8所得)位数据即为用户数据。

2、用户数据【TP-UDL:TP-User-Data-Length】

后面的字符串“4F60597D”即为用户数据。经过反编译得出为“你好”

转自:http://blog.csdn.net/linfeng999/article/details/6601328

参考:http://www.dzjs.net/html/zonghejishu/2007/0515/2080.html

PS:若发送者手机号长度为奇数,则手机号码倒数第二位是补码F

------------------------------一段解码的程序片段

    else if (strstr(szMess, "+CMGR:"))
    {
        //第一段——短信中心码段
        /*前两位“ 08”08* 2=16,即表示“08”后面的16位字符串为短信中心号码信息;
        后两位“91”,此“91”为短信息中心号码类型,91是TON/NPI。*/
        char *pPDUPos = strstr(sMess.GetBuffer(), "0891");
        sMess.ReleaseBuffer();
        //第二段——手机号码段
        /*SMS_DELIVER的第一个8 位(固定格式)(2位)
        发送方号码长度(2位)
        消息类型,同第一段的91(2位)
        发送方号码(发送方号码长度*2位)*/
        char arraySrcNumLength[2]={'\0'};
        memcpy(arraySrcNumLength, pPDUPos+2+(8*2)+2, 2);//08+中心号长度+SMS_DELIVER的第一个8 位(固定格式)
        int nSrcNumLength;
        sscanf(arraySrcNumLength, "%02X", (char*)&nSrcNumLength);
        
        // 解码电话号码 ******************************
        char *pSendPhoneNumber = new char[nSrcNumLength+1];
        memset(pSendPhoneNumber, 0, nSrcNumLength+1);
        int i=0;
        for (i=0; i<nSrcNumLength/2; i++)
        {
            *(pSendPhoneNumber+i*2) = pPDUPos[2+(8*2)+6+i*2+1];
            *(pSendPhoneNumber+i*2+1) = pPDUPos[2+(8*2)+6+i*2];
        }
        //如果奇数位电话号码,最后一位是补码F,同时nSrcNumLength加1
        if(nSrcNumLength%2==1)
        {
            *(pSendPhoneNumber+i*2) = pPDUPos[2+(8*2)+6+i*2+1];
            nSrcNumLength++;
        }
        // 解码电话号码 ******************************
        /*第三段——协议标识(TP-PID) 00,2位
        用户信息编码方式(TP-DCS),2位:00:表示7-bit 编码, 08:表示UCS2 编码,04:表示8-bit 编码。*/
        //第四段——短信息发送的日期、时间与时区类型(DateTime Zone Type)【TP-SCTS:】
        /*前6位日期,中6位时间,最后两位时区,共14位*/
        //第五段——用户数据长度与用户数据
        /*前两位用户数据长度,后面(用户数据长度*2)位是数据内容,*/
        char szTPDC[2];
        memcpy(szTPDC, pPDUPos+2+16+6+nSrcNumLength+2, 2);
        int nUserDataLengthPos = 2+16+6+nSrcNumLength+4+14;
        char arrayUserDataLength[2]={'\0'};
        memcpy(arrayUserDataLength, pPDUPos+nUserDataLengthPos, 2);
        int nUserDataLength;
        sscanf(arrayUserDataLength, "%02X", (char*)&nUserDataLength);
        char* pCont = NULL;
        char pUserData[512];
        memset(pUserData, 0, 512);
        if(szTPDC[1]=='8' || szTPDC[1]=='4')
            memcpy(pUserData, pPDUPos+nUserDataLengthPos+2, nUserDataLength*2);
        else if(szTPDC[1]=='0')
            strcat(pUserData, pPDUPos+nUserDataLengthPos+2);
        
        pCont = GetASCIICode(pUserData, nUserDataLength*2, szTPDC[1]);//短信内容(文本

        CString str;
        str.Format("收到短信 - 发送者号码(%s):%s", pSendPhoneNumber, pCont);
        ptrDlg->XDBMsgSMS(pSendPhoneNumber, "XEIM_SYSTEM", pCont);
        delete[] pSendPhoneNumber;
        delete[] pCont;
        pSendPhoneNumber = NULL;

        ptrDlg->AddErrorInfo(str);
    }

 

//将4位16进制转换为多字节(例如短信编码到普通字符串)
char* GetASCIICode(const char* lpText, int nLen, char cTPDCS)
{
    if(cTPDCS=='0')//7Bit编码
        return GetASCIICode7Bit(lpText, nLen);
    else if(cTPDCS=='4')//8Bit编码)
    {
        char* tmp = new char[strlen(lpText)];
        memcpy(tmp, lpText, strlen(lpText));
    }

    if(nLen==-1)
        nLen = strlen(lpText);

    WCHAR *newTmp = new WCHAR[nLen/4+1];
    *(newTmp+nLen/4) = '\0';
    int i=0;
    for(i=0; i<nLen/4; i++)
    {
        char buf[5];
        memcpy(buf, lpText+i*4, 4);
        buf[4]='\0';
        sscanf(buf, "%04X", newTmp+i);
    }

    int iSize = WideCharToMultiByte(CP_ACP, 0, newTmp, -1, NULL, 0, NULL, NULL);
    char* tmp = new char[iSize];
    WideCharToMultiByte(CP_ACP, 0, newTmp, -1, tmp, iSize, NULL, NULL);
    delete[] newTmp;

    return tmp;
}

char* GetASCIICode7Bit(const char* lpText, int nlen)
{
    char buf[3];
    int* pTempInt = new int[nlen/2+1];//将原始字符串先从16进制char转换成十进制int
    int i=0, j=0;
    for(i=0; i<nlen/2; i++)
    {
        memcpy(buf, lpText+i*2, 2);
        sscanf(buf, "%02X", pTempInt+i);
    }

    char* tmp = new char[nlen/2+1];
    int Point=0;//每7次就转换出8个ASCII码
    for(i=0; j<nlen/2; i++, j++/*, pTempInt++*/)
    {
        int nRet = 0;
        if(Point==0)
            nRet = (*(pTempInt+i)<<Point) & (0xFF>>(Point+1));
        else
            nRet = ((*(pTempInt+i)<<Point) & 0x7F) |
            (*(pTempInt+i-1)>>(8-Point));

        sprintf(tmp+j, "%c", nRet);
        if(Point==6)//每7位可以多转换一个ASCII码
        {
            j++;
            nRet = *(pTempInt+i)>>1;
            sprintf(tmp+j, "%c", nRet);
        }

        Point=(Point+1)%7;
    }

    delete[] pTempInt;

    return tmp;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值