面部黄金比例图:wappush短信详解

来源:百度文库 编辑:九乡新闻网 时间:2024/05/07 02:37:20
WapPush编码
(2009-06-09 22:51:50)转载
标签: 杂谈
分类: MSN搬家
20110402索引整理,便于各位查阅.
1.WapPush编码
2.Wappush编码续--分包研究
3.长短信及wappush分包实施
-------------------------------------------------------------------------------------------
网上找了些WapPush编码资料,大部分不怎么靠谱。
贴个比较靠谱的link:http://hi.baidu.com/pisvia/blog/item/38e2b335dd97c78ea71e122b.html
总结一下目前为止查阅资料的收获。
公司的应用环境是通过CMPP协议,将编码好的WapPush数据发送到手机。以下内容可能仅局限于此.
WapPush编码有三个组成部分,WDP,WSP,WBXML..网上资料对WBXML的描述比较多,对WDP及WSP部分描述比较少。
WDP及WSP协议内容也比较庞杂,此处讨论的是以最少字段实现WapPush,WDP及WSP协议具体内容见wap-230-wsp-20010705-a及
wap-259-wdp-20010614-a
看一个例子
一个完整的字节流为:
0605040B8423F081060603AE81EA8D4A02056A0045C6080C037761702E73696E612E636F6D00010374657374E6B58BE8AF95000101
其中WDP:0605040B8423F0
# 06      | User-Data-Header (UDHL) Length = 6 bytes
# 05      | UDH IE identifier: Port numbers
# 04      | UDH port number IE length
# 0B 84 | Destination port
# 23 F0 | Originating port
这是单包情况下,多包情况需要额外5字节分包信息,相应长度字段0x06->0x0B
下面是多出来的5字节内容
# 00 | UDH IE identifier: SAR
# 03 | UDH SAR IE length
# 04 | Datagram ref no.
# xx | Total number of segments in datagram
# yy | Segment count
WSP部分类似HTTP头域部分,指定一些头域信息。基本上就是Content-Type和Content-Length,PDU类型及流水号
WSP:01060603AE81EA8D4A
# 01      | Transaction ID (流水号)
# 06      | PDU type           (push)
# 06      | Header length (头域部分长度,不包括PDU类型及流水号)
# 03 AE | Content-type: application/vnd.wap.sic   (03表示头域Content-type,AE表示头域值application/vnd.wap.sic   下面2个类似)
# 81 EA | charset=utf-8
# 8D 4A | content-length: 74 (wbxml部分长度)
然后就是最后的WBXML部分
WBXML部分基本上是一样的差异不大,网上WapPush讲的最多的也是这一部分,这里就不详细描述了。
WBXML:02056A0045C6080C037761702E73696E612E636F6D00010374657374E6B58BE8AF95000101
测试中的问题,WSP有个不定长整形数据(uintvar),就是超过8bit的数值进行拆分,低7位存放数据,高位补1表示有后续。最大32bit。
比较诡异的是。对协议看有些字段定义的是uintvar,但是不符合规范的填充也是允许.这也是很多资料WSP第一个字段为0x81(0x01高位补1)的原因。
另一个比较诡异的地方是WSP部分content-length填充的长度实际为WBXML字节数×2...不知道为啥.但是工作正常.
这个地方网上很多资料也是填的数值不一,有填字节数的,有字节数以uintvar方式填充的。
多包情况没有试,看资料是将WBXML部分拆开,如果这样不知道手机收到的时候是所有包收全展示,还是收一个展示一部分(数据不全,多半不会是这种方式)。
目前为止就是这样,以后有新的发现再补充...
补完计划一:
这两天把代码移植到AIX..记录一下其中的问题.准确的说不算wappush的问题,而是移植过程中的问题。
1.UTF8与GB编码转换,AIX和Linux下用iconv转换,本来想用wcstombs和wctomb替换MultiByteToWideChar和WideCharToMultiByte;但是发现死活只能转到UCS2..后来上网查阅资料发现Aix和Linux下可以用iconv的库来转换很方便,而且还有对应windows的库 =-=.不过windows部分的转换代码写好了就懒得换了。iconv的使用中还有一个问题,就是在调用iconv_open的时候指定源和目标字符集的时候要用大写“UTF8,GB2312”,奇怪的是小写Linux没问题,Aix会转换失败,改成大写就都可以跑。这个问题当时卡了很久,比较崩溃。还有个地方需要注意iconv的参数outlen输入的时候需要是outbuf的实际长度,执行完后outlen的值会被修改为outbuf的剩余长度。
2.字符串比较函数
windows平台。
函数: stricmp、strnicmp.
Linux&Aix平台。
函数: strcasecmp、strncasecmp.
3.网络字节序的问题
上面这些wappush报文对应到一个WAPpush的位置如下所示:
引用位置:
http://jxxms.iteye.com/blog/806790Wap push的发送应该有两种途径,一个是通过PAP协议,另外一个是通过SMPP协议。其中SMPP是一个基本协议,在中国主要有三个派生的协议:中国移动的CMPP协议,中国联通的SGIP(在CDMA上面好像是
ETIP),以及小灵通的SMGP。据说中国移动没有在公网开放PAP协议,于是只好使用CMPP协议来进行wap push发送了,不知道其他的运营商是否也是如此。上面提到的各种协议都是公开的,通过Google搜索就可以得到。光得到协议没有什么意义,因为你还需要知道wap push网关的IP和Port,以及运营商给你发放的帐号和密码。而最为头痛的是,你研究下载下来的协议的时候,至少会遇到下列几个大问题:
1、协议可能不正确
2、协议内容语焉不详,或者具有二义性
3、没有任何实际例子
如果你能够进入运营商的实验室会更好,因为可以得到一些技术支持。不过也不要开心的太早,你还会遇到下列问题:
1、运营商并不清楚协议的技术细节,因为实际上是由运营商的硬件提供商所代为开发的(至少我看起来的是这样的)
2、硬件提供商的技术人员也不一定清楚非常深入的技术细节,天晓得到底谁才知道这些该死的协议的技术细节。
3、在实验室里面的技术人员至少可以帮你抓一个包,指出你的包跟标准的包有什么区别。如果没有大的区别的时候仍然出错,那技术人员也无能为力了。
在开发Wap push的时候跟实验室的技术人员聊天,据说以前其他的人员连接上去的时候,还曾经遇到过MD5算法不标准导致验证不通过的问题。幸亏我用的.NET,不会出现这种问题,不然验证不通过你还不知道是验证的明文格式不对,还是其他的什么问题,总之是不可能进行调试的。而我遇到的问题则主要是文档迷惑人造成的,比如说协议里面有一个字段叫做SourceAddress,实际上要求你填入的是SpID,而SourceID的字段却要求你填入SourceAddress。看完那堆文档我的大脑几乎要被搅成浆糊了,希望你会好一点。
实际上这个CMPP的协议是用来发送短消息的,包括普通的短消息、彩信以及WapPush等。具体你要发送什么类型的消息,需要设置MessageType字段和MessageContent字段。因此如果你要发送的事彩信,那么还得找跟彩信相关的资料,尤其是数据包结构。而我则非常郁闷的发现,关于WapPush数据包的资料非常的少,少的不可置信。前面那个中文资料算是帮了我一把,对比了实验室抓取的另外一个数据包之后,至少看懂了部分的内容,并且某个品牌的手机能够收到。可是里面提到的WapPush Header1之类的内容到底是什么意思,以及如何编写其他标记等,统统不知道。
Goo了半天才搞懂,原来WapPush包发送的内容实际上跟PAP发送的XML是一回事,但是经过了压缩。压缩之后的格式叫做WBXML,这种格式将一些标记用代码来表示,例如数值0x01表示上一个标记结束(之类的)。然而WBXML的缩略标记分为两部分,一部分是所有类型的XML都通用的,另一部分是不同类型的XML有着不同的解释。而WBXML的Spec只提到了:
2  "-//WAPFORUM//DTD WML 1.0//EN" (WML 1.0)
3  "-//WAPFORUM//DTD WTA 1.0//EN" (WTA Event 1.0)
4  "-//WAPFORUM//DTD WML 1.1//EN" (WML 1.1)
这三种类型,而我们所做的WapPush使用的是
5  "-//WAPFORUM//DTD SI 1.0//EN
关于这里面的内容我没有能够找到任何资料。即使到了这里,我们也只是了解了Header后面的内容,而MessageContent里面的内容则需要从
0B05040B8423F00003030101         ’Wap Push Header 1
29060603AE81EA8DCA   'Wap Push header 2
这里开始发送,但是这些是什么东东呢?我不知道,等高手来解答了。不过在这里我可以提供另外一组有效的Wap Push Header:
//    0x06, 0x05, 0x04, 0x0B, 0x84, 0x23, 0xF0,     ' Wap Push Header 1 (见上面的WDP)
//    0x25, 0x06, 0x01, 0xAE,                                     ' Wap Push header 2 (WSP)
另外再奉送一下我实验成功的(至少在索爱T618上面必然成功的)一个MessageContent结构:
// 第一部分 WapPushHeader1:
static private readonly byte[] WapPushHeader1 = new byte[]
{
//    0x06, 0x05, 0x04, 0x0B, 0x84, 0x23, 0xF0,
0x0B, 0x05, 0x04, 0x0B, 0x84, 0x23, 0xF0, 0x00, 0x03, 0x03, 0x01, 0x01, (其实这是上文说到的WDP)
};
// 第二部分 WapPushHeader2:
static private readonly byte[] WapPushHeader2 = new byte[]
{
//    0x25, 0x06, 0x01, 0xAE,
0x29, 0x06, 0x06, 0x03, 0xAE, 0x81, 0xEA, 0x8D, 0xCA, (上文提到的WSP)
};
// 第三部分 WapPushIndicator (and some other things):
static private readonly byte[] WapPushIndicator = new byte[]
{
0x02, 0x05, 0x6A, 0x00, 0x45, 0xC6, 0x0C, 0x03,
};
// 第四部分是一个UTF8编码的WapPush连接的Url地址,
// 用户在手机上收到该短信之后点击“下载”或者“连接”之类的按钮之后,
// 就会转到这一个地址。
// 注意,Url地址需要把"http://"去掉,
// 因为上面的WapPushIndicator倒数第二个0x0C就是href = "http://"
// 第五部分Wap Push Display Text Header:
// 其中的0x00是上面的WapPushUrl文字结束标志
// 0x01是上面的标志(Indicator倒数第三个的0xC6)的结束符
//

static private readonly byte[] WapPushDisplayTextHeader = new byte[]
{
0x00, 0x01, 0x03,
};
// 第六部分是一个UTF-8编码的消息文字,用户收到该消息之后就会显示这里面的内容。
// 第七部分是消息结束部分,0x00是消息文字的结束部分,后面两个是上面一些标志的结束符。
static private readonly byte[] EndOfWapPush = new byte[]
{
0x00, 0x01, 0x01,
};
将这几个部分顺序组合起来,就是MessageContent的内容了。

wap push格式
00     ’SMSC Len。用手机上设置短信中心号码
51     ’submit type
00     ’SMS_TP_Message_Reference type
0B    ’对方电话的长度
A1     ’Number type
13175639296F6       ’电话号码:13573629696
00     ’SMS_TP_PID
F5     ’SMS DCS
A744         ’SMS available date
0B05040B8423F00003030101         ’Wap Push Header 1(WDP)
29060603AE81EA8DCA   'Wap Push header 2(WSP)
02
05  '-//WAPFORUM//DTD SI 1.0//EN
6A  'UTF-8
00
45  '
C6  '08  '
0C  'href="http://
03  '字符串开始
687474703A2F2F3231382E35392E3133382E35343A32303030  'URL:   http://218.59.138.54:2000
00  'URL 字符串结束
01  '>
03  '内容描述字符串开始
'这里就是显示给用户的内容,用utf-8编码。
9A6C5EF6671D       '内容描述:马延朝
00  '内容描述字符串结束
01  '"
01  '

可以只能显示很少的汉字,请高手指点怎么分包发送更多的汉字?
一下方法是经过验证的。
TrxID  =一个随机数
fullStr = "0605040B8423F0" & TrxID & "0601AE"
fullStr = fullStr & "02056A0045C6080C03"
fullStr = fullStr & StrToHex(TheURL, 2)
fullStr = fullStr & "001103" & "0102"
fullStr = fullStr & "40494400080AC307" & Format(Now, "yyyymmddhhmmss")
fullStr = fullStr & "10C304" & "20990101" & "0103"
fullStr = fullStr & StrToHex(MServiceName, 2) & "000101"
分段发送的
例如  URL:wap.gd.monternet.com/?userType=B&serviceID=04020028 提示信息:神秘激情地带,江湖儿女情长神秘激情地带,江湖儿女情长神秘激情地带,江湖儿女情长
第一包:
0B05040B8423F0000355020155060403AE81EA02056A0045C60C037761702E67642E6D6F6E74657
26E65742E636F6D2F3F75736572547970653D42267365727669636549443D303430323030323800
070103E7A59EE7A798E6BF80E68385E59CB0E5B8A62CE6B19FE6B996E584BFE5A5B3E68385E995BF
E7A59EE7A798E6BF80E68385E59CB0E5B8A62C
第二包:
0B05040B8423F00003550202E6B19FE6B996E584BFE5A5B3E68385E995BFE7A59EE7A798E6BF80E6
8385E59CB0E5B8A62CE6B19FE6B996E584BFE5A5B3E68385E995BF000101 ,解释可参考WDP WSP,我就不具体说了
0B是头的总长度
05040B8423F0是固定的,表示接下来是一个WAP PUSH
分包的关键是0003550201,对应GSM 03.40里9.2.3.24.1,00表示是Concatenated Short Messages,03是长度,55是reference number,楼主在这儿固定编码会有问题的,如果同时下发两条这样的多包短信给同一个手机,手机就区分不开了,02表示分成2个短信发送,01是当前包的序号。
一个扩展包wappush包是这么构成的
WDP + WSP + SI/SL
如果长度超常(短信一个包的Content不要超过140)
就要分解成
WDP1 + (WSP+SI/SL)的part 1
WDP2 + (WSP+SI/SL)的part 2
...
WDPN + (WSP+SI/SL)的part N
如单包
WDP: 06 05 04 0B 84 23 F0
WSP: ...
SI/SL:...
双包是
第1包
WDP: 0B 05 04 0B 84 23 F0 00 03 01 02 01
Part1: ...
// 00 - UDH IE Tag
// 03 - UDH SAR IE Length
// 01 - Refrence
// 02 - Total Packet
// 01 - Current Packet
第2包
WDP: 0B 05 04 0B 84 23 F0 00 03 01 02 02
Part2:...
WDP参考相关文档。
=====================================================
首先,构造一个Push消息体:
02
05  '-//WAPFORUM//DTD SI 1.0//EN
6A  'UTF-8
00
45  '
C6  '08  '
0C  'href="http://
03  '字符串开始
这里就是url从"http://"以后的那部分的每个字符的ASCII码
00  '字符串结束
0A  'created=
C3  '时间
07  '7个字节,也可以是04,下面就只需要年月日就可以了
20 03 01 01 00 00 00 '年,月,日,时,分,秒,格式如何一看就明白吧。
10  'si_expires=
C3  '时间
07  '跟上面一样
20 04 01 01 00 00 00
01  '>
03  '字符串开始
这里就是显示给用户的内容,用utf-8编码。
utf-8编码,英文字符直接用ascii码;中文如果unicode是(二进制)abcdefgh ijklmnop,
那么utf-8就会变成1110abcd 10efghij 10klmnop
00  '字符串结束
01  '"
01  '

有了Push消息体之后,需要在前面增加一个Push PDU
81  'transaction id (connectionless WSP)
06  'pdu type (06=push)
06  'Headers len
03 AE 81 EA    'content type: application/vnd.wap.sic; charset=utf-8
8D    'content-length
XX  '这里就是Push消息体的长度。如果消息体长度小于128,那么就要加上128。例如是93个字节,那么需要填入DD
'至于大于127怎么处理,按照协议好像应该是这样,例如原来的二进制abcdefgh,那么就要弄成两个字节:
'1000000a 1bcdefgh,但是尝试还没成功
在然后,还要在前面增加一个UDH
06 'User Data Header Length (6 bytes)
05 'UDH Item Element id (Port Numbers)
04 'UDH IE length (4 bytes)
0B 84   'destination port number
23 F0   'origin port number
如果所有这些加起来大于140个字节,那么就需要修改UDH头,分成两条短消息串联。但是没有尝试成功。
发送的时候,udhi=1,pid=0,dcs=4
Nokia 3650/7650肯定OK,motorola t720肯定ok,siemens 3118,3618肯定不行,其他的还没尝试。
同样的技术可以用来发送mms通知、fundown的铃声图片。
需要解决的问题:长于127字节/两条短信的时候该怎么办。