天天看點

手機短信的PDU編碼和解碼

共有三種方式來發送和接收SMS資訊:Block Mode, Text Mode和PDU Mode。其中PDU Mode被所有手機支援,可以使用任何字元集,這也是手機預設的編碼方式。

發送短消息常用Text和PDU(Protocol Data Unit,協定資料單元)模式。使用Text模式收發短信代碼簡單,實作起來十分容易,但最大的缺點是不能收發中文短信;而PDU模式不僅支援中文短信,也能發送英文短信。PDU模式收發短信可以使用3種編碼:7-bit、8-bit和UCS2編碼。7-bit編碼用于發送普通的ASCII字元,它将一串7-bit的字元(最高位為0)編碼成8-bit的資料,每8個字元可“壓縮”成7個;8-bit編碼通常用于發送資料消息,比如圖檔和鈴聲等;而UCS2編碼用于發送Unicode字元。在這三種編碼方式下,PDU串的使用者資訊(TP-UD)段最大容量(可以發送的短消息的最大字元數)分别是160、140和70。這裡,将一個英文字母、一個漢字和一個資料位元組都視為一個字元。

PDU串的使用者資訊長度(TP-UDL),在各種編碼方式下意義有所不同。7-bit編碼時,指原始短消息的字元個數,而不是編碼後的位元組數。8-bit編碼時,就是位元組數。UCS2編碼時,也是位元組數,等于原始短消息的字元數的兩倍。如果使用者資訊(TP-UD)中存在一個頭(基本參數的TP-UDHI為1),在所有編碼方式下,使用者資訊長度(TP-UDL)都等于頭長度與編碼後位元組數之和。如果采用GSM 03.42所建議的壓縮算法(TP-DCS的高3位為001),則該長度也是壓縮編碼後位元組數或頭長度與壓縮編碼後位元組數之和。 

PDU相當于一個資料包,它由構成消息(SMS)的資訊組成。作為一種資料單元,它必須包含源/目的位址、保護(有效)時間、資料格式、協定類型和正文,正文長度可達140位元組,它們都以十六進制表示。PDU結構根據短消息由移動終端發起或以移動終端為目的而不同。每條消息可以發送140個位元組,由于本系統中最長的資料串沒有超過140個位元組,是以資料均可以用一條消息來發送。

一般的PDU編碼由A B C D E F G H I J K L M十三項組成。

A:短資訊中心位址長度,2位十六進制數(1位元組)。

B:短資訊中心号碼類型,2位十六進制數。

C:短資訊中心号碼,B+C的長度将由A中的資料決定。

D:檔案頭位元組,2位十六進制數。 

E:資訊類型,2位十六進制數。

F:被叫号碼長度,2位十六進制數。

G:被叫号碼類型,2位十六進制數,取值同B。

H:被叫号碼,長度由F中的資料決定。

I:協定辨別,2位十六進制數。

J:資料編碼方案,2位十六進制數。

K:有效期,2位十六進制數。

L:使用者資料長度,2位十六進制數。

M:使用者資料,其長度由L中的資料決定。J中設定采用UCS2編碼,這裡是中英文的Unicode字元。

PDU編碼協定簡單說明

例1 發送:SMSC号碼是+8613800250500,對方号碼是13693092030,消息内容是“Hello!”。從手機發出的PDU串可以是

08 91 68 31 08 20 05 05 F0 11 00 0D 91 68 31 96 03 29 30 F0 00 00 00 06 C8 32 9B FD 0E 01

對照規範,具體分析:

分段 含義 說明

08 SMSC位址資訊的長度 共8個八位位元組(包括91)

91 SMSC位址格式(TON/NPI) 用國際格式号碼(在前面加‘+’)

68 31 08 20 05 05 F0 SMSC位址 8613800250500,補‘F’湊成偶數個

11 基本參數(TP-MTI/VFP) 發送,TP-VP用相對格式

00 消息基準值(TP-MR) 0

0D 目标位址數字個數 共13個十進制數(不包括91和‘F’)

91 目标位址格式(TON/NPI) 用國際格式号碼(在前面加‘+’)

68 31 96 03 29 30 F0 目标位址(TP-DA) 8613693092030,補‘F’湊成偶數個

00 協定辨別(TP-PID) 是普通GSM類型,點到點方式

00 使用者資訊編碼方式(TP-DCS) 7-bit編碼

00 有效期(TP-VP) 5分鐘

06 使用者資訊長度(TP-UDL) 實際長度6個位元組

C8 32 9B FD 0E 01 使用者資訊(TP-UD) “Hello!”

例2 接收:SMSC号碼是+8613800250500,對方号碼是13693092030,消息内容是“你好!”。手機接收到的PDU串可以是

08 91 68 31 08 20 05 05 F0 84 0D 91 68 31 96 03 29 30 F0 00 08 30 30 21 80 63 54 80 06 4F 60 59 7D 00 21

對照規範,具體分析:

分段 含義 說明

08 位址資訊的長度 個八位位元組(包括91)

91 SMSC位址格式(TON/NPI) 用國際格式号碼(在前面加‘+’)

68 31 08 20 05 05 F0 SMSC位址 8613800250500,補‘F’湊成偶數個

84 基本參數(TP-MTI/MMS/RP) 接收,無更多消息,有回複位址

0D 回複位址數字個數 共13個十進制數(不包括91和‘F’)

91 回複位址格式(TON/NPI) 用國際格式号碼(在前面加‘+’)

68 31 96 03 29 30 F0 回複位址(TP-RA) 8613693092030,補‘F’湊成偶數個

00 協定辨別(TP-PID) 是普通GSM類型,點到點方式

08 使用者資訊編碼方式(TP-DCS) UCS2編碼

30 30 21 80 63 54 80 時間戳(TP-SCTS) 2003-3-12 08:36:45  +8時區

06 使用者資訊長度(TP-UDL) 實際長度6個位元組

4F 60 59 7D 00 21 使用者資訊(TP-UD) “你好!”

詳細解析:

 0891683108200505F011190D91683105155694F50008FF10008FF044F60597D

   <1>短信中心位址字段:0891 

    08:Address-Lengt(位址長度),短資訊中心位址長度為8個位元組,是(91)+(683108200505F0)的長度,8個8位位元組

 91位址類型:10010001       Bit7:1。始終為1       Bits 6,5,4:Type-of-Number(号碼類型):001,代表Internation Number。也即是号碼前加“+”。注意:對某些比較特殊的号碼,例如手機與小靈通的互通時,這裡不能設定為001,而要設定成000,代表号碼前沒有“+”,否則無法接收。

下面是GSM03.40協定号碼類型的解釋:

 0 0 0   Unknown

 0 0 1   International number

 0 1 0   National number

 0 1 1   Network specific number

 1 0 0   Subscriber number

 1 0 1   Alphanumeric(coded according to TS03.38 7-bit default alphabet)

 1 1 0   Abbreviated number

 1 1 1   Reserved for extension

 ll not interpret reserved values but will store them as received.

       Bits 3,2,1,0:Numbering-plan-identification(号碼鑒别),0000—未知,0001—ISDN/電話号碼(E.164/E.163),1111—留作擴充;一般預設為0001,表示電話号碼類型的。下面是GSM03.40号碼鑒别的解釋:

Bits3 2 1 0

0 0 0 0    Unknown

0 0 0 1    ISDN/telephone numbering plan (E.164/E.163)

0 0 1 1    Data numbering plan (X.121)

0 1 0 0    Telex numbering plan

1 0 0 0    National numbering plan

1 0 0 1    Private numbering plan

1 0 1 0    ERMES numbering plan (ETSI DE/PS 3 01-3)

1 1 1 1    Reserved for extension

All other values are reserved.

<2>短信中心号碼:683108200805F0 

一個位元組内反轉,8613800280500,如果長度為奇數則需要加“F”補齊。比如号碼為:+8613505165495,去掉"+"後在末尾添加F變為:8613505165495F,再将手機号碼的奇數位和偶數位的相交換為683105155694F5

<3>FirstOctet字段:1119

     (1)11       包含TP-MTI(2bit),TP-RD(1bit),TP-VPF(2bit),TP-RP(1bit),TP-UDHI(1bit),TP-SRR(1bit)

二進制表示形式:0 0 0 10 0 01

TP-MTI:01 TP-Message-Type-Indicator(消息類型訓示符)

     Bit1,0:00—讀出(Deliver); 01—送出(Submit)

Bit1,0:01訓示為SMS-SUBMIT類型 

下面是GSM03.40的解釋:

 bit1 bit0  Message type

 0     0    SMS-DELIVER (in the direction SC to MS)

 0     0    SMS-DELIVER REPORT (in the direction MS to SC)

 1     0    SMS-STATUS-REPORT (in the direction SC to MS)

 1     0    SMS-COMMAND (in the direction MS to SC)

 0     1    SMS-SUBMIT (in the direction MS to SC)

 0     1    SMS-SUBMIT-REPORT (in the direction SC to MS)

 1    1      ReservedTP-RD:0  TP-Reject-Duplicates(是否拒絕相同重複消息)

   Bit2:0—接受複制; 1—拒絕複制

Bit2:0   訓示短消息中心接收未轉發的具有相同TP-MR的消息。

 Bit 2:

 0    Instruct the SC to accept an SMS-SUBMIT for an SM still held in the  SC which has the same TP-MR and the same TP-DA as a previously submitted SM from the same OA.

 1    Instruct the SC to reject an SMS-SUBMIT for an SM still held in the   SC which has the same TP-MR and the same TP-DA as the  previously submitted SM from the same OA. In this case an  appropriate TP-FCS value will be returned in the SMS-SUBMIT-REPORT.

TP-VPF:10   TP-Validity-Period-Format(有效期格式)

Bit4,3::00—不提供(Not present);01—預留;  10—整型(标準),指使用相對格式;11—提供8位位元組的一半(Semi-Octet Represented) 

下面是GSM03.40的解釋:

bit4 bit3

0   0      TP-VP field not present

1   0      TP-VP field present and integer represented (relative)

0   1      Reserved

1   1      TP-VP field present and semi-octet represented (absolute)

TP-SRR:0    TP-Status-Report-Request

   Bit5:    1:需要報告,0:不需要報告。

Bit 5:

0       A status report is not requested

1       A status report is requested

TP-UDHI:0   TP-User-Data-Header-Indicator(使用者資料頭标示)   Bit6:   1:含頭資訊  0:不含頭資訊,訓示這是一個SMS消息,沒有使用者資料頭,EMS(增強消息業務)消息需要設定。圖檔鈴聲這些都是包含頭部資訊的.文本不包含頭部資訊

Bit  6

0     The TP-UD field contains only the short message

1     The beginning of the TP-UD field contains a Header in addition to the  short message

TP-RP:0     TP-Reply-Path(回複路徑)   Bit7:    1:設定回複路徑,0:沒有設定回複路徑。

下面是GSM03.40解釋:

Bit 7:

0:  TP-Reply-Path parameter is not set in this SMS-SUBMIT/DELIVER

1:  TP-Reply-Path parameter is set in this SMS-SUBMIT/DELIVER

(2)消息參考值TP-MR (TP-Message-Reference):19如果使用"00" 值代表讓電話自己設定消息參考值.

<4> 對方号碼字段:0D913105155694F5 

    0D:目标位址數字個數,共13個十進制數(不包括91和‘F’)

    91:位址類型,同短信中心号碼設定.

   3105155694F5:目标手機号碼。

<5>上層協定辨別TP-PID(TP-Protocol-Identifier):00

     一般設定為00,表示普通GSM,點對點  <6> 資料編碼設定TP-DCS(TP-Data-Coding-Scheme):08 

    訓示TP-UD的編碼方式。08代表Unicode方式。參照GSM03.38協定:

Bit 3,2

00    Default alphabet

01    8 bit

10    UCS2 (16bit) [10]

11    Reserved

  <7>有效期TP-VP(TP-Validity-Period):FF

    FF表示最大。

  <8> 使用者資料長度TP-UDL(TP-User-Data-Length):4

      使用者資料實際長度。注意不同編碼下使用者長度定義不同。

   <9>使用者資料 :4F60597D     "你好"的Unicode編碼

你:0x4F60;好:0x597D

  2:手機接收的PDU串

 0891683108200505F0040D91683105155694F5000850208151754500044F60597D

   <1>短信中心位址字段:0891683108200505F0,即是+8613800250500

 <2>FirstOctet :04        其二進制代碼:00000100

    TP-MTI:00

    TP-MMS(TP-More-Message-to-Send):1 短信中心沒有更多的消息發送

    TP-SRI: 0

    TP-UDHI:0

    TP-RP:  0

 <3>發送方号碼 :0D91683105155694F5   即+8613505165495

 <4>協定辨別: 00    TP-DCS 點對點

 <5>編碼方式: 08    TP-DCS Unicode編碼

   <6>短信中心時間    50208151754500  

     位元組反轉05/02/18 15:57:45 最後的00代表時區,這裡為0

   <7>使用者資料長度 :4 

 <8>使用者資料:4F60597D      

   中文“你好”的Unicode編碼

c執行個體

//7-bit 編碼

int16 _Encode7bit(const char *pSrc, uint8 *pDest, uint16 nSrcLen)
{
	int16 nChar;	
	uint8 nLeft, *pEnd;

	nChar = 0;
	pEnd = pDest;

	while (nSrcLen--)
	{
		nChar &= 7;
		if (nChar == 0)
		{
            nLeft = *pSrc;
		}
        else
		{
			*pEnd++ = (*pSrc << (8-nChar)) | nLeft;
			nLeft = *pSrc >> nChar;
        }
		pSrc++;
		nChar++;
	}

	if (nChar != 8)
	{
		*pEnd++ = nLeft;
	}

    return (int16)(pEnd-pDest);
}
//7-bit 解碼
int16 _Decode7bit(char *pDest, uint8 *pSrc, int16 nSrcLen)
{
	int32 nByte;
	char *pEnd;
	uint8 nLeft;

	pEnd = pDest;
	nByte = nLeft = 0;

    while (nSrcLen--)
	{
		*pEnd++ = ((*pSrc << nByte) | nLeft) & 0x7f;
		nLeft = *pSrc >> (7-nByte);
		
		nByte++;
        if (nByte == 7)
		{
			*pEnd++ = nLeft;
			nByte = 0;
			nLeft = 0;
		}
		pSrc++;
	}
    
	if (*(pEnd-1) == 0)
	{
		pEnd--;
	}
    *pEnd = 0;

	return (pEnd-pDest);
}