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;
}