第 1 部分
本文将指导开发人员使用 JSR 180 API 通过 SIP 协议进行异步通信。
移动应用程序需要从服务器接收信息,或者通过服务器从移动用户处接收信息。当移动设备与服务器进行同步通信时,一切工作都会正常进行。您只需要打开连接发送请求,服务器将使用相同的连接返回响应。
HTTP 协议非常适合同步事务,当人们访问遍布各地的网站时,这种同步事务每天都会发生十亿次。然而,当连接不存在,但 Web 服务器却要联系 Web 浏览器时,问题就会变得很棘手。对于北美洲而言,现在正处在税收时期,请考虑下面这个问题。如果使用 Web 应用程序提交税务信息,那么您是如何获取接受或拒绝税务文件的响应信息呢?您可以通过异步协议(如 SMTP,或称作电子邮件)获取响应,或者在同步协议(如 HTTP 协议)中采用轮询机制来检查税务应用程序的状态。
考虑一个经典的问题:如果移动应用程序需要接收一些事件的通知,您就需要使用同步协议或异步协议来执行轮询操作。如果您使用过 Java ME,那么应当知道 MIDP 1.0 之后的所有 Java ME 设备都提供了对 HTTP 协议的支持。因此,本文的目的在于让开发人员能够使用 JSR 180 API 实现基于 SIP 协议的异步通信。幸运的是:JSR 180 是 MSA 标准 的一部分,因此将会有越来越多的移动设备支持此 API。
在下面的示例代码中,我将展示两个分别使用 SIP 和 JSR 180 API 的 MIDlet。但在开始之前,您将了解运行此示例所需的所有资源:
* Sun Wireless Toolkit 2.5 for CLDC
是的,您甚至不需要通过两台计算机来运行发送和接收应用程序。可以在同一计算机上同时运行这两个示例。
SipReceiver.java MIDlet
本文假设您具备创建 MIDlet 的经验,因此不再涉及有关 MIDlet 生命周期或构造函数的内容。如果需要,您可以通过以下教程快速掌握 Java ME 的基础知识:学习资源:MIDlet 生命周期、无线开发教程,第 1 部分、移动 Java 技术介绍。让我们看代码的第一行:
import javax.microedition.sip.*;
public class SipReceiver extends MIDlet implements CommandListener{
public Display display;
public long startTime;
public Form. form;
public TextField portTextField;
public ImageItem userImageItem;
public Image userImage;
public Command startCommand;
public Command exitCommand ;
public SipConnectionNotifier scn = null;
public SipServerConnection ssc = null;
将 SipServerConnection 类绑定到端口并监听发出的请求。为了使这一切起作用,SipServerConnection 需要协同 SipConnectionNotifier 一起工作。SipConnectionNotifier 是您需要实现的一个接口,当您的 MIDlet 接收到 SIP 请求时,它可以向您发出通知。从以下类声明中可以看出,我并没有实现 SipConnectionNotifier 接口,因为我选择使用内部类来处理所有的 I/O 操作。以下代码片段显示了内部类 DataTransfer 的详细内容。
class DataTransfer extends Thread implements SipServerConnectionListener {
public void run(){
try {
if(scn != null)
scn.close();
scn = (SipConnectionNotifier) Connector.open("sip:" + portTextField.getString());
scn.setListener(this);
form.append("Listening to port: " + scn.getLocalPort());
} catch(Exception ex) {
ex.printStackTrace();
}
}
public void notifyRequest(SipConnectionNotifier scn) {
try {
ssc = scn.acceptAndOpen();
if(ssc.getMethod().equals("MESSAGE")) {
String contentType = ssc.getHeader("Content-Type");
String contentLength = ssc.getHeader("Content-Length");
int length = Integer.parseInt(contentLength);
if((contentType != null) && contentType.equals("text/plain")) {
InputStream is = ssc.openContentInputStream();
int i=0;
byte testBuffer[] = new byte[length];
i = is.read(testBuffer);
String message = new String(testBuffer, 0, i);
form.append(new StringItem("Subject:", ssc.getHeader("Subject")));
form.append(new StringItem("Message:", message));
}
ssc.initResponse(200);
ssc.send();
}
} catch(IOException ex) {
form.append("Exception: "+ex.getMessage());
}
}
}
应该注意两个明显的问题:
* 内部类扩展了 Thread 类,因为需要在单线程中执行所有的阻塞 I/O 操作。
* 内部类实现了 SipConnectionNotifier,这在前面已解释过。由于该类实现了 SipConnectionNotifier ,因此在接收到新请求时会调用 notifyRequest() 方法。
您已经了解了接收 SIP 消息所需的大部分工作。接下来,我们来看看发送消息所需的代码。
SipSender.java MIDlet
和前面的示例相同,我将使用内部类实现所有繁重的任务。我们直接查看内部类代码部分,了解其实现细节。
class DataTransfer extends Thread implements SipClientConnectionListener{
public void run() {
SipClientConnection sc = null;
try {
sc = (SipClientConnection) Connector.open(addressTextField.getString());
sc.setListener(this);
String message = messageTextField.getString();
sc.initRequest("MESSAGE", null);
sc.setHeader("From", addressTextField.getString());
sc.setHeader("Subject", subjectTextField.getString());
sc.setHeader("Content-Type", "text/plain");
sc.setHeader("Content-Length", "" + message.length());
OutputStream s = sc.openContentOutputStream();
os.write(message.getBytes());
os.close();
} catch(Exception e) {
e.printStackTrace();
}
}
public void notifyResponse(SipClientConnection scc) {
try {
scc.receive(1);
form.append("notifyResponse: "+scc.getStatusCode()+" "+scc.getReasonPhrase());
scc.close();
} catch(Exception e) {
form.append(e.getMessage());
}
}
}
再次指出几个问题:
* 我们采用内部类扩展 Thread 类是出于性能原因,因为在生成 I/O 请求时,您不希望所有的应用程序都暂停运行。
* 我们需要实现接口 SipClientConnectionListener,这要求实现回调方法 notifyResponse()。这样,我们可以检查消息的状态码。SIP 的状态码和 HTTP 很相似,因此状态 200 就意味着已成功接收并理解了您的请求。
结束语
如您所见,借助 JSR 180 API,您可以轻松地使用 SIP 协议发送和接收消息。最重要是:SIP 响应代码是以 HTTP 为模型的,因此在使用该协议的过程中您会觉得非常惬意。在第 2 部分,我们将深入探索 SIP 协议,并了解使用注册器或代理的优势。
阅读(1816) | 评论(0) | 转发(0) |