利用VB 实现短消息收发
摘要:近来,笔者用VB 开发了一套PC 机上的短消息收发软件,本文根据笔者的实际开发经
验整理而得。文中介绍了在计算机上实现短消息收发的模式,重点描述了PDU 模式,包括
PDU 模式下的UCS2 编码、解码原理,以及发送与接收PDU 串的编制方式,在此基础上介绍
了利用VB 中的MSCOMM 控件,实现短消息收发的核心程序。
关键字:短消息收发、PDU 模式、UCS2 编解码、UNICODE 码、AT 指令、MSCOMM 控件
正文:
现在,短消息收发软件得到越发广泛的应用,从政府机关、学校到广大的传媒机构,
直至诸多的企事业单位,颇受使用者欢迎。首先,手机用户的普及为这类软件的出现提供了
可能,而使用这类软件,与人们传统惯用的打电话、发电子邮件等通讯方式相比,有独到的
优点,它能将信息及时送达对方,不会像查收信件(或电邮)存在时间上的延误,也不存在
类似于打电话占线或无人接听之类的烦恼;短消息收发软件可以实现消息收发双方的实时交
互,用它还可以实现消息的群体发送或定时发送等。最近,笔者尝试用VB 来开发一套实现
短消息收发功能的信息系统。至提笔之时,整套系统已经开发完毕。鉴于篇幅的原因,笔者
不可能将整个系统一一尽数,而只能将开发过程中与短消息收发功能相关的一些技术要点和
心得体验与众读者进行分享。
一、短消息收发的实现模式
目前,计算机串口上连接GSM MODEM,用它向手机发送短消息,是比较适合于小型项目
开发的一种实现模式。这种方法要求对AT 指令集和串口编程比较熟悉。在开发过程中笔者
使用的是索尼爱立信公司的GM29 模块。
这种方法收发短消息又分三种模式:BLOCK 模式、TEXT 模式和PDU 模式。BLOCK 模式已
是昔日黄花,现在用的很少了; TEXT 模式则只能发送ASCII 码,它不能发送中文的UNICODE
码——确切地讲,从技术上来说是可以用于发送中文短消息的,但是国内的手机基本上不支
持;而PDU 模式开发起来则较为复杂,它需要编写专门的函数来将文本转换为PDU 格式,但
PDU 模式被所有手机支持,可以使用任何字符集,它也是手机默认的编码方式。笔者在开发
中正是选用的PDU 模式。
二、PDU 模式
用PDU 模式收发短消息可以使用三种编码: 7-bit 编码、8-bit 编码和UCS2 编码。 7-bit
编码用于发送普通的ASCII 字符;8-bit 编码通常用于发送数据消息,如图片或铃声等;UCS2
编码用于发送Unicode 字符。由于笔者在系统中要实现中文短消息的发送,所以选择用UCS2
编码,即中文Unicode 码。
(一)UCS2 编码原理
所谓UCS2 编码,是将单个的字符(1-2 个字节)按ISO/IEC10646 的规定,转变为16 位
的Unicode 宽字符。即将单个的字符转换为由四位的‘0’-‘9’、 ‘A’-‘F’的数字和字
母组成的字符串。待发送的消息以UCS2 码的形式进行发送。
先介绍VB 中的Ascw()和Hex()函数。Ascw()函数用来求出字符串的Unicode 值;Hex()
函数返回表示十六进制数字值的字符串。对这两个函数用例子来说明:
?Ascw("您")
24744
?Hex(24744)
60A8
____________________________________________________________w_w__w_._p_a_p_e_r._e_d_u_.c_n
因此,字符“您”的UCS2 编码为:60A8(十六进制数字)。
(二)发送PDU 串的编制分析
通过UCS2 编码我们得到中文Unicode 码,接着就可以进行发送PDU 串的编制了。从表
面上看,PDU 串是ASCII 码串,同样由‘0’-‘9’、 ‘A’-‘F’这些数字和字母组成。它
们是8 位字节的十六进制数,或者BCD 码十进制数。PDU 串除了包含所发送的消息本身外,
还包含很多其它参数信息,如服务中心号码、目标号码和编码方式等。现用一个实例说明发
送PDU 串的结构和编排方式。
例:08 91 683108100005F0 31 00 0D 91 683125503956F9 00 08 C2 06 60A8597DFF01
参照规范,具体分析:
分段 含义 解释说明
08 SMSC 地址信息的长度 共8 个八位字节(包括91)
91 SMSC 地址格式(TON/NPI) 用国际格式号码(在前面加‘+’)
68 31 08 10 00 05 F0 SMSC 地址 8613800100500,补‘F’凑成偶数个
31 基本参数(TP-MTI/VFP) 要求发送回复
00 消息基准值(TP-MR) 0
0D 目标地址数字个数 共13 个十进制数
91 目标地址格式(TON/NPI)
A1:国内格式
91:国际格式
81:未知,+86 可带可不带。
68 31 25 50 39 56 F9 目标地址(TP-DA) 8613520593659,补‘F’凑成偶数个
00 协议标识(TP-PID) 是普通GSM 类型,点到点方式
08
用户信息编码方式
(TP-DCS)
00:表示7-bit 编码, 08:表示UCS2 编码,
04:表示8-bit 编码。
C2 有效期(TP-VP) 5 分钟
06 用户信息长度(TP-UDL) 实际长度6 个字节
60 A8 59 7D FF 01 用户信息(TP-UD) “您好!”
表一 发送PDU 串的编制分析
这里需要注意的几点:
①.比较SMSC 地址分段:68 31 08 10 00 05 F0 与真实SMSC 地址8613800100500F(为
了凑足14 位,在末尾补F),不难发现只需将前者奇偶位对调即可得到后者。同样,目标地
址分段68 31 25 50 39 56 F9 与实际目标地址13520593659F 之间的关系也是如此。
②.若“SMSC 地址信息的长度”分段的值为00,则意味着SMSC 地址字符串的长度为零,
PDU 串的“SMSC 地址格式”段和“SMSC 地址”段将省去。且将使用SIM 卡设置的SMSC 地址。
上例中的PDU 串变为:
00 31 00 0D 91 683125503956F9 00 08 C2 06 60A8597DFF01
③. 对于用户信息长度,可通过VB 中的Len 函数求得,如“您好!”,用Len(“您好!”)
得到是3,那么3*2=6 即为用户信息长度06(这里要转换为16 进制,并且是两位)。
④.用户信息(TP-UD)段最大容量是140 字节,所以在UCS2 编码方式下,可发送短消息
的最大字符数是70 个。
(三)UCS2 解码
接收短消息时,需要将收到的用UCS2 编码(用户信息编码方式为08)的消息串解码成
字符串字符。与编码时的Ascw()相对应,VB 中的Chrw()函数用来将Unicode 值转化为字符
串字符。只要对Unicode 码求Unicode 值,调用Chrw()便可转换成字符串字符。
中_国__科__技__论__文__在__线_______________________________________________w_w_w__.p_a_p_e_r_.e_d_u_._cn
例: UCS2 码60A8,求得它的Unicode 值为24744
?Chrw(24744)
您
当然,在接收消息时,可能不仅收到UCS2 格式编码的PDU 串,也可能是7bit 编码格式
(TP-DCS 为00)或8bit 编码格式(TP-DCS 为04)的PDU 串。对这两种情况,笔者也编了
相应的解码算法,且它们的算法要相对简单,由于着重介绍UCS2 解码,7bit 与8bit 解码
就不再多介绍了。
(四)接收PDU 串的编制分析
接收PDU 串和发送PDU 串结构是不完全相同的。通过一个实例来分析,假定收到的短消
息其PDU 串为:
08 91 68 31 08 10 00 05 F0 04 0D 91 68 31 25 50 39 56 F9 00 08 40 40 60 31 35 30
23 06 60 A8 59 7D FF 01
参照规范,具体分析:
分段 含义 解释说明
08 SMSC 地址信息的长度 共8 个八位字节(包括91)
91 SMSC 地址格式(TON/NPI) 用国际格式号码(在前面加‘+’)
68 31 08 10 00 05 F0 SMSC 地址 8613800100500,补‘F’凑成偶数个
84 基本参数(TP-MTI/MMS/RP) 接收,无更多消息,有回复地址
0D 回复地址数字个数 共13 个十进制数(不包括91 和‘F’)
91 回复地址格式(TON/NPI) 国际格式
68 31 25 50 39 56 F9 回复地址(TP-RA) 8613520593659,补‘F’凑成偶数个
00 协议标识(TP-PID) 是普通GSM 类型,点到点方式
08 用户信息编码方式(TP-DCS) UCS2 编码
40 90 10 31 35 30 23 服务时间戳(TP-SCTS) 2004-09-01 13:53:03
06 用户信息长度(TP-UDL) 实际长度6 个字节
60 A8 59 7D FF 01 用户信息(TP-UD) “您好!”
表二 接收PDU 串的编制分析
通过分析,我们可以获取其中的有用信息。如:短信服务中心号码是+8613800100500,
发送方号码是13520593659,发来的消息内容是“您好!”,以及发送时间是:2004-09-01
13:53:03。
三、短消息发送和接受的功能实现
打开VB 6.0,从工程菜单的部件选项中添加Microsoft Comm Control 6.0 控件到工具
栏,在窗体里添加COMM 控件,点右健进行属性设置:在“通用”选项选择可用的端口,设
置属性参数;在“缓冲”选项设置输入输出缓冲值,设置R阀值(设为1)和S阀值(设为
0);在“硬件”选项选中RTS 有效。初始化:
MSComm1.CommPort = 1 '选择串口COM1
MSComm1.Settings =" 9600,N,8,1" '9600 波特,无奇偶校验,8 位数据,一个停止位
MSComm1.InputLen = 0 '读入整个缓冲区
(一)、发送消息的程序实现
前面已经对发送PDU 串的编制进行了分析,对于编好的PDU 串,就可利用COMM 控件,
通过相应的AT 指令来实现短消息的发送。用来实现消息发送的AT 指令是:AT+CMGS 。以前
面用的发送PDU 串为例,即发送内容为“您好!”,接受方手机号为13520593659;需要说明
的是,在此笔者省去了对SMSC 地址格式和SMSC 地址这两个分段的编写,采用了SIM 卡设置
的SMSC 地址。即发送的PDU 串为:0031000D91683125503956F90008C20660A8597DFF01,具
中_国__科__技__论__文__在__线_______________________________________________w_w_w__.p_a_p_e_r_.e_d_u_._cn
体程序如下:
If MSComm1.PortOpen = False Then MSComm1.PortOpen = True '确认打开串口
MSComm1.Output = "AT+CMGF=0" + vbCr '以PDU 模式发送短信
TimeDelay '延时处理
MSComm1.Output = "AT+CMGS=" & Str(15 + length) + vbCr
TimeDelay
MSComm1.Output="0031000D91683125503956F90008C20660A8597DFF01"
MSComm1.Output = Chr$(26)
TimeDelay
buf = MSComm1.Input 'buf 是自定义的一个string 型的变量
If InStr(buf, "OK") Then '若发送成功
MsgBox "发送成功!", vbInformation, "系统消息"
Else If InStr(buf, "ERROR") Then '若发送失败
MsgBox "发送失败!", vbInformation, "系统消息"
End if
在程序语句:MSComm1.Output = "AT+CMGS=" & Str(15 + length) + vbCr 中, 15
表示所发送的PDU 串中31000D91683125503956F90008C206 的位数,而length 的取值(此
例中为6)为60A8597DFF01 的位数。
程序中的TimeDelay 是笔者自定义的用来处理延时操作的函数,因为在连续的两个
AT 指令之间需要设置一定的间隔时间(设为了1 秒),为每一条发送的指令提供响应时间。
(二)、接收消息的程序实现
先介绍几个相关的AT 指令,(1)AT+CPMS,优先信息存储。该命令用来指定读写信息的
存储区域。在这里设置AT+CPMS=”SM”,”SM”,”SM”。使收到的短消息存储在GM29 模
块中的SIM 卡上,不是存储在模块本身的内存中。(2)AT+CNMI,新信息指示, 可用于设定
当有某类短消息到达时,如何处置它。在此不对它的详细指令语法多做介绍了,这里设置为
AT+CNMI=3,1,这样,当收到一条新消息时,系统就会收到一个提示信息,格式如:+CMTI:
"SM",1 。(3)AT&W, 用来保存所做的设置。
在保存了上述设置后,当软件收到新消息到达的提示信息时(假定是:+CMTI: "SM",1。
说明它存在了SIM 卡上,并且序号为1),可以发送AT+CMGR 指令,用它来读取该指定位置
的消息。我们仍用前面进行接收PDU 串分析时使用的PDU 串为例,程序实现如下:
If MSComm1.PortOpen = False Then MSComm1.PortOpen = True
MSComm1.InBufferCount = 0
MSComm1.Output = "AT+CMGR=1" + vbCr
TimeDelay
同时设置COMM 控件的OnComm 事件:
Private Sub MSComm1_OnComm()
Dim buf As Variant
Select Case MSComm1.CommEvent
Case comEvReceive
MSComm1.InputMode = comInputModeText
Do
buf = buf & MSComm1.Input
Loop Until InStr(buf, "OK" & vbCrLf)
Case Else
中_国__科__技__论__文__在__线_______________________________________________w_w_w__.p_a_p_e_r_.e_d_u_._cn
End Select
End Sub
这时,COMM 控件读取回的全部内容存放在变量buf 中,此例中buf 值为:
+CMGR: 1,,22
0891683108100005F0040D91683125503956F90008404060313530230660A8597DFF01
OK
有时候可能并不知道新消息在SIM 卡上的实际存储位置的序号,或新消息可能不止一
条,这时可以用AT+CMGL 指令来读取。它用来同时列出SIM 卡上的信息: AT+CMGL=0,用
来列出SIM 卡上所有未读取的新消息; AT+CMGL=4,列出SIM 卡上的所有消息。程序实现
如下:
If MSComm1.PortOpen = False Then MSComm1.PortOpen = True
MSComm1.InBufferCount = 0
MSComm1.Output = "AT+CMGL=0" + vbCr
TimeDelay
同样要设置OnComm 事件,这时buf 为:
+CMGL: 1,0,,22
0891683108100005F0040D91683125503956F90008404060313530230660A8597DFF01
OK
因为此时SIM 卡上只有一条新消息,所以buf 只列出了一条,若同时有多条,将会全部
列出。
这时,我们可以取其中的接收PDU 串:
0891683108100005F0040D91683125503956F90008404060313530230660A8597DFF01
进行解码分析,获得消息内容。具体分析前面已经做了详细介绍,在此就不再累赘了。
参考文献:
范逸之。 《利用Visual Basic 实现串并行通信技术》 清华大学出版社 2001.3
中_国__科__技__论__文__在__线_______________________________________________w_w_w__.p_a_p_e_r_.e_d_u_._cn
正文
利用VB 实现短消息收发2005-09-29 20:21:00
【评论】 【打印】 【字体:大 中 小】 本文链接:http://blog.pfan.cn/iamben250/5457.html
阅读(5269) | 评论(0)
版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!
评论