基于Java的校园GSM短信服务平台的设计与实现

时间:2022-05-01 01:44:14

基于Java的校园GSM短信服务平台的设计与实现

摘要:手机短信成为人们的主要通信方式之一,尤其是短信通信和计算机数据库的结合,已经成为企业单位内部传递更新资讯的重要手段;基于PDU的UCS2编码设计了一个校园短信平台的方案,用于学生通过手机短信查询成绩,并用Java实现了该方案。

关键词:JAVA通信开发包;短信;GSM Modem;PDU模式;UCS2编码

中图分类号:TP311文献标识码:A文章编号:1009-3044(2008)16-21194-03

A Feasibility Design and Actualization to the GSM Campus SMS Service Platform Based on Java

LUO Hai-tao

(School of Informatics, Guangdong University of Foreign Studies, Guangzhou 510420, China)

Abstract: Short message of cell phone becomes major communication method, especially the combination of short message and database has become important method of communication between employees of company. Designed a Campus SMS Serive Platform based on UCS2 coding of PDU mode, which is used for student to query about grade by cell phone message, and actualized the platform using Java.

Key words: Java Communicatoin API;Cell phone Message;GSM Modem;PDU mode;UCS2 coding

1 引言

互联网无疑是20世纪末最热门的关键字。然而,和2000年以访问者人数、浏览量、点击率为关键词不同的是,2002年以来IT业最流行的话题是通信业务和互联网的整合,其中最密切的关键词是短信。无线增值业务是建立在移动通信网络基础上除了语音以外的数据服务,包括短信、彩信、彩铃、IVR、WAP、KJAVA/BREW、PDA等。我国无线增值业务的用户不断增长,目前约80%的手机用户使用此业务。无线增值业务收入增长水平已超过了其他电信业务的增长水平。短信服务以其收费低廉,传输方便,新颖的特色服务,受时空和网络状况通信环境制约少的特点,深受人们欢迎。

2 基于web的短信接入服务

短信中心将用户发送的短信内容发给与其相连的短信网关,短信网关根据短信发送号码即SP(Service Provider, 短信服务提供商,一般指各大门户网站)的服务代码,将短信内容发给相应的SP。用户接收短信业务即MT业务。提供此项业务的sp将短信内容发给与其连接的短信网关,短信网关根据用户手机号段,发给用户归属的短信中心。采用此种方式,使用人必须与移动服务商(如中国移动)签订短信网关接入协议。此种方式好处是可以获得移动服务商的技术和服务支持,而且直接由SMSC(Short Message Service Center,短信服务中心)提供服务,服务质量有保证。但是针对校园短信服务平台的设计,采用这种方式不太实际。原因之一是移动的考核程序繁复,个人用户申请困难,而且必须支付一定费用。企业单位内部一般采用基于PC端的短信接入服务,企业不需要与移动服务商签订任何协议,只需要拥有一台GSM Modem,将一般市面上可以买到的SIM卡(或专用短信卡)插入modem,再与PC服务器连接,启动服务器监听程序,即可搭建企业内部的GSM短信服务中心。此方式的实现方便,费用低廉,本文所述的校园短信服务平台将采用此方式实现。

3 系统设计和实现

3.1 系统总体功能和结构

本系统采用Java语言设计一个校园短信服务平台并实现学生查询成绩功能,用计算机服务器作为后台信息处理器,通过串口控制短信控制终端GSM Modem进行短信接收和发送。通过获得学生用户的查询请求,返回操作结果,实现短信查询成绩,系统框图如图1所示。

其中PC服务器监听程序通过Java Communication API(Java通信包)连接和控制串口设备(指GSM Modem)和基于轮询和消息驱动方式的端口监听,封装AT指令对查询请求进行PDU(Protocol Data Unit, 协议数据单元)解码,连接数据库查询并返回结果,将结果进行PDU编码通过GSM Modem以一般短信形式将结果返回用户。

3.2 串口控制

在使用端口通讯前,必须知道系统哪些端口可用的,如果使用的端口已被占用时,会抛出PortInUseException异常。以下代码列出系统中所有可用的端口,使用CommPortIdentifier类的getPortIdentifiers方法可以获得一个Enum对象,其中包含系统所有的串口,每一个串口对应一个CommPortIdentifier类的实例。这里用while语句遍历它们并且打印出来:

Enumeration en = CommPortIdentifier.getPortIdentifiers();

CommPortIdentifier portId;

while (en.hasMoreElements()) {

portId = (CommPortIdentifier) en.nextElement();

if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {

System.out.println(portId.getName());}}

使用端口前,必须先打开它,本设计为COM1:

CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier("COM1");

SerialPort port = (SerialPort)portId.open(this.getClass().getName(), 5000);

打开后再设置端口:

port.setSerialPortParams(9600,port.DATABITS_8,port.STOPBITS_1,port.PARITY_NONE);

这些设置数据就像Windows里“超级终端”里的设置一样,以上实参都采用默认值。经过上面的设置,如果只进行简单的读写已经可以了。但是要实现像“超级终端”那样和用户交互,还必须进行下面的一些设置:

首先执行串口操作的类要实现SerialPortEventListener接口,该接口用于监听串口,以便随时对到达的数据进行处理(消息驱动,监听模式)。如:

public class PortController implements SerialPortEventListener {}

接着在open()语句设置:

port.notifyOnDataAvailable(true); // 当数据到达时唤醒接口方法serialEvent()

port.addEventListener(this); // 设置当前类为监听类

到此为止,端口设置全部完成。之后使用端口读写数据。首先必须设置输入输出流对象:

InputStream in = port.getInputStream();

OutputStream out = port.getOutputStream();

CommPortIdentifier负责端口的初始化和开启和管理占有权。CommPort是和实际输入和输出功能有关。CommPort的getInputStream()可以获取端口的输入流,它是java.io.InputStream接口的一个实例。我们可以用标准的InputStream的操作接口来读取流中的数据。相应的,CommPort的getOutputStream可以获得端口的输出流,这样就可以往串口输出数据了。

in.read(/* 读入数组缓存 */);

out.write(/* 写入内容 */); // 写入串口的内容必须为byte(字节)类型

写数据的时候使用一个while(true)死循环获得用户输入实现“超级终端功能”,当然为了能正常退出程序,必须设立一个退出条件:

while (true) {

input = br.readLine(); // input为用户输入字符串,用了BufferedReader缓冲

if (input.equalsIgnoreCase("exit")) {break;} // 用户输入exit则退出循环

out.write(input.getBytes()); // 写入数据 }

最后具体化SerialPortEventListener 的接口方法:

public void serialEvent(SerialPortEvent event) throws Exception {

if (event.getEventType() == event.DATA_AVAILABLE) {

in.read();

// 处理输出如System.out.println()等}}

现在可以启动程序,输入AT指令"at",返回"ok",模拟“超级终端”程序成功实现。最后使用完的端口必须将其关闭,这样可以让程序交出控制权,令其它的程序可以使用它,否则再使用该端口时会抛出端口被占用的错误。调用CommPort类的close()方法可以将其关闭,关闭端口前应该先关闭两个输入输出流:

in.close();

out.close();

port.close();

3.3 编码和解码

由欧洲电信标准组织ETSI (Europe Telecommunication Standards Institute) 制定的GSM标准共有三种方式用来发送和接收SMS信息:Block Mode、Text Mode和PDU Mode。Block Mode已经逐渐淡出人们的视线目前基本不再使用。Text Mode是纯文本方式,一般用于发送英文和数字,虽然理论也可用于发送中文短信,但中文属于Unicode字符,转换编码繁琐。PDU Mode被所有手机支持,可以使用任何字符集,是手机编码的默认方式。在PDU Mode中,又细分7-bit、8-bit和UCS2方式。其中UCS2编码用于发送Unicode字符,支持中文,本设计即采用这种编码。

在本设计中,用于实现编码的类命名为PDUEncoder,该类包含方法:format(), encodeCenter(), encodeTo(), encodeSMS(), removeF(), encode()和内部类Reply。format()用于对号码格式化,如前面加上'86'。对号码的编码比较简单,首先将字符串奇偶位字符互换,长度为奇数的末尾补一个'F'成为偶数,然后在前面或后面加上该PDU串长和特定标识,如短信中心的编码:

8613800200500 //末位补F/奇偶互换

683108200005F0 // 前面加上国际码91

91683108200005F0 // 计算串长"91683108200005F0".length()/2 并转换为16进制加到最前面

0891683108200005F0 // 结果

短信内容编码对应方法为encodeSMS()。每个Unicode字符占16位表示, PDU格式规定含有Unicode字符的编码高低位字节互换,即高8位和低8位要对换。对此Java提供了现成的方法:

anStringObject.getBytes("utf16-be")

该方法可以取得一个按utf16-be编码的byte数组,而utf16-be就符合上述要求(其中be是"BigEndian"大字节优先的缩写),然后可以用此数组转换为16进制整数表示的PDU串了(这里必须采用utf16-be编码,否则生成的PDU串GSM不能识别)。接着转换成16进制字符串,首先应将byte转换为对应byte值的整型(int),再把它们转换为16进制数,经测试可以通过下面方法实现(b为byte[]):

for (int i=0; i

String tmp = Integer.toHexString((int)b[i]).toUpperCase();

if (tmp.length()

tmp = "0" + tmp;

tmp = removeF(tmp);

output += tmp;} //将每个字节的转换结果加入到PDU串

最后用encode()方法将所有字段的PDU串和“短信编码”(UCS2一定要用"08")、回复类型等特殊标记加上,并计算出PDU串长并加入到内部类Reply中。Reply类含有两个成员变量,value用于存放PDU串的值,length用于存放PDU串长。PDU串长位数不限但不能超过GSM规定的长度(GSM03.42规定UCS2编码UDL

PDU的UCS2解码基本是编码的逆操作,本设计类名为PDUDecoder,方法有getPhone(),getMessage(), isPDU(), decode()和内部类Query。isPDU()用于测试输入是否PDU串,这里用了一个简单的方法,就是测试PDU串的第40和41两位是否"08",该数值表示UCS2编码。getPhone()用于获取发送方号码(方便返回成绩查询结果),PDU的56、57位是发送方号码长度,根据此长度可用substring()方法获得整个号码的PDU串,然后执行编码的逆向操作,奇偶位互换再减去末位补上的'F':

for (int i=0; i

sender += String.valueOf(PDUArray[i+1]);

sender += String.valueOf(PDUArray[i]); }

上一篇:基于系统辨识的系统模型 下一篇:数据库系统安全保护技术应用探讨