手机SMS的PDU编码

这是自己和结合别人的资料对PDU编码的理解,可能有错误,请指正。

目前,发送短消息常用Text和PDU(Protocol Data Unit,协议数据单元)模式。使用Text模式收发短信代码简单,实现起来十分容易,但最大的缺点是不能收发中文短信;而PDU模式不仅支持中文短信,也能发送英文短信。PDU模式收发短信可以使用3种编码:7-bit、8-bit和UCS2编码。7-bit编码用于发送普通的ASCII字符,8-bit编码通常用于发送数据消息,UCS2编码用于发送Unicode字符。
 PDU的构成
PDU是由一串由“0-9”及“A-F”组成。表面上看起来就是一组16进制的数所组成的。

 1:一个手机发送的一个PDU串
 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编码 

参考资料:<1>GSM03.40协议
                  <2>短消息PDU字段分析与实现    赵波 王凯写    

另外还有一些网友的资料,谢谢了

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的C语言程序,用于将文本消息转换为PDU格式: ``` #include <stdio.h> #include <string.h> void encode_pdu(const char* message, const char* phone_number, const char* center_number, char* pdu) { int i, j; int message_length = strlen(message); int phone_number_length = strlen(phone_number); int center_number_length = strlen(center_number); char hex_length[3]; char pdu_header[32]; char pdu_message[256]; char pdu_phone_number[32]; char pdu_center_number[32]; // 将消息长度转换为16进制字符串 sprintf(hex_length, "%02X", message_length); // 将消息编码方式设置为7位ASCII码 strcpy(pdu_header, "00"); // 将短信中心号码转换为BCD码 for (i = 0, j = 0; i < center_number_length; i += 2, j++) { pdu_center_number[j] = ((center_number[i] - '0') << 4) | (center_number[i + 1] - '0'); } if (center_number_length % 2 == 1) { pdu_center_number[j - 1] |= 0xF0; j++; } pdu_center_number[j] = '\0'; // 将手机号码转换为BCD码 for (i = 0, j = 0; i < phone_number_length; i += 2, j++) { pdu_phone_number[j] = ((phone_number[i + 1] - '0') << 4) | (phone_number[i] - '0'); } if (phone_number_length % 2 == 1) { pdu_phone_number[j - 1] |= 0xF0; j++; } pdu_phone_number[j] = '\0'; // 将消息转换为7位ASCII码 for (i = 0; i < message_length; i++) { pdu_message[i * 2] = (message[i] & 0x7F); pdu_message[i * 2 + 1] = ((message[i] >> 7) & 0x01); } pdu_message[i * 2] = '\0'; // 将PDU数据按顺序拼接起来 sprintf(pdu, "%s%s%s%s%s%s", pdu_header, hex_length, pdu_center_number, "00", "0A", pdu_phone_number); strcat(pdu, "00"); // TP-PID strcat(pdu, "00"); // TP-DCS strcat(pdu, "00"); // TP-VP strcat(pdu, pdu_message); } int main() { char pdu[512]; encode_pdu("hello", "13800138000", "+8613800000500", pdu); printf("%s\n", pdu); return 0; } ``` 在这个程序中,`encode_pdu`函数接受文本消息、手机号码和短信中心号码作为参数,并将PDU格式编码后的数据写入`pdu`数组中。程序使用了C语言中的字符串操作函数,例如`strlen`、`strcpy`和`strcat`。 在函数中,先计算出消息长度的16进制表示,并将消息编码方式设置为7位ASCII码。然后将短信中心号码和手机号码分别转换为BCD码,并在末尾添加F或0F。接下来将消息转换为7位ASCII码,并将PDU数据按顺序拼接起来,最后将PDU数据写入`pdu`数组中。 在`main`函数中调用`encode_pdu`函数,将文本消息、手机号码和短信中心号码作为参数传递给它,并打印出生成的PDU数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值