Dorado 7 : 长连接(SEUG)

技术特点

  1. 默认基于Http LongPolling技术实现,未来可能扩展出WebSokcet的实现。
  2. 实现了单一Page中的长连接自动合并功能,即在单一Page中无论开发者利用Dorado建立多少个长连接,Dorado都只占用个一个物理长连接,并在此物理连接的基础上构建n个虚拟连接。此功能未来可能会进一步扩展,以实现跨Page的连接自动合并。
  3. 消息收发的自动合并,当客户端或服务端在短时间内频繁的利用长连接发送消息时,Dorado会自动对将一批消息合并为一次物理Request或Response,从而避免浏览器过度频繁的与服务器建立Http连接。

建立连接

客户端

在客户端建立一个长连接的方法是直接调用dorado.Socket.connect()方法,该方法有两个参数——options和callback。callback顾名思义就是长连接建立成功后的回调方法,而options则是长连接的选项,options参数可以包含如下的几个重要的子参数(具体参考API文档):

  • service —— 字符串。服务端ExposedService(可暴露远程服务)的名称。这里的ExposedService就是我们在编写Ajax操作的服务端代码时所使用的那种服务。
  • parameter —— 任意对象,可以为空。即建立连接时传递给服务端的参数。
  • onReceive —— 当收到服务端发来的消息时触发的事件。
  • onDisconnect —— 当连接断开时触发的事件。

dorado.Socket.connect()方法的返回值是socket对象,我们可以通过这个对象在做后面的处理.

例如...

var socket = dorado.Socket.connect({ service: "test#messageService" }, function() {
	alert("Socket connected.");
});

服务器端

定义长连接服务端的代码的方法几乎与定义Ajax服务端代码的方法完全一样,唯一的不同是你必须在方法的参数中保留一个名为socket的参数,该参数的类型为com.bstek.dorado.view.socket.Socket。通过该参数我们方便与客户端进行消息收发操作。例如...

@Component
public class Test {
	@Expose
	public void messageService(Socket socket) {
		... ...	
	}
}

如果客户端指定了建立连接时的参数,那么这里的messageService方法中也可以通过自动适配参数来接收parameter中的数据,方法同Ajax操作的一样,此处不再累述。

收发消息

客户端

客户端收发消息的操作比较简单,要发送消息可以直接使用socket对象的send()方法,该方法包含三个参数:

  1. type —— 字符串,消息类型。可以是任意字符串。
  2. data —— 任意对象,消息内容。
  3. callback —— 消息发送成功的回调方法,即服务端确认收到消息后才会触发的回调方法。

例如...

socket.send("chat", "吃了吗?");

客户端接收消息需要使用Socket对象的onReceive事件。例如...

var socket = dorado.Socket.connect({ service: "test#messageService", onReceive: function(arg) {
	alert("收到了来自服务器的消息..." + "\ntype:" + arg.type + "\ndata:" + arg.data);
}});

服务器端

服务端发送消息的方法与客户端非常相似,例如...

socket.send(new Message("消息类型", "消息内容"));

服务端接收消息的方法有两种——阻塞式和非阻塞式。

阻塞式的消息接收

使用阻塞式消息接收通常是在一个独立的线程中,例如我们可能是这样来定义ExposedService的...

@Expose
public void messageService(Socket socket) {
	(new SocketServerThread(socket) {
		@Override
		protected void run(Socket socket)  {
			while (socket.isConnected()) {
				try {
					Message message = socket.receive();	// 阻塞方法
					... ...
					socket.send(new Message("chat", "呵呵"));
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}).start();
}
非阻塞式的消息接收

非阻塞式的消息接收是利用Socket对象的监听器,它的使用场景相对自由。例如:

@Expose
public void messageService(Socket socket) {
	socket.addReceiveListener(new SocketReceiveListener() {
		public void onReceive(Socket socket, Message message) {
			... ...
			socket.send(new Message("chat", "呵呵"));
		}
	});
}