三、WebSocket客户端

1.说明

WebSocket作为 HTML5的一个重要组成部分,在现今逐渐成为一个主流的标准.Voovan 提供对 WebSocket 客户端的支持.下面我们就简单的介绍一下: 首先通过 HttpClient 类的 webSocket 方法即可简单的实现对 WebSocket 的访问.同时基于 WebSocketRouter 类实现对onOpenonRecivedonSentonClose四个方法的支持。

以下几个类是 WebSocket 开发中常用的类:

  • WebServer 类: 该类的 Socket 方法提供给我们一个注册 WebSocket 服务的入口.
  • WebSocketRoute 类: 一个 WebSocket 业务处理类,Voovan 采用异步的方式调用这个类的各种事件.
  • WebSocketSession 类: 一个 WebSocket 会话类,提供了诸如:send,close,isConnect 等基于会话的方法.
  • WebSocketFilter 类: WebSocket 消息过滤器类

2.材料准备

首先我们来介绍一个HttpClient.webSocket方法

  1. public void webSocket(String urlString, WebSocketRouter webSocketRouter) throws SendMessageException, ReadMessageException {
  • urlString: websocket 访问路由地址.
  • webSocketRouter: websocket 路由处理对象.如果要开发一个 WebSocket 类,首先我们要调用webSocket方法,并注册一个路由和 WebSocket 的路由处理类WebSocketRouter.

接下来我们来熟悉一下WebSocketRouter类的定义

  1. /**
  2. /**
  3. * websocket 连接打开
  4. * @return 收到的缓冲数据
  5. */
  6. public abstract ByteBuffer onOpen(WebSocketSession session);
  7. /**
  8. * websocket 收到消息
  9. * @param message 收到的缓冲数据
  10. * @return 收到的缓冲数据
  11. */
  12. public abstract ByteBuffer onRecived(WebSocketSession session, ByteBuffer message);
  13. /**
  14. * websocket 消息发送完成
  15. * @param message 发送的消息
  16. */
  17. public abstract void onSent(WebSocketSession session, ByteBuffer message);
  18. /**
  19. * websocket 关闭
  20. */
  21. public abstract void onClose(WebSocketSession session);

最后我们来介绍一下样例的信息:

  • 访问的地址: http://127.0.0.1:28080/websocket
  • onOpen 发送 OPEN_MSG
  • onRecived 收到后发送 RECIVE_MSG
  • onSent 输出发送的消息
  • onClose 输出 close如何处理消息的发送和接受?

如何接受消息:

在 onRecive 事件中的第二个参数 message 就是 WebSocket 从客户端接收到的数据.我们们可以在这里讲数据转换成需要个对象后进行处理.

  • 如何发送消息:

在 Voovan HttpClient 中向客户端发送消息有三种方式:

  • onOpen 事件返回的数据将会被发送至客户端, 返回 null 时不发送任何消息.
  • onRecive 事件返回的数据将会被发送至客户端, 返回 null 时不发送任何消息.
  • 调用 WebSocketSession.send 来发送数据. 也就是说,我们在 WebSocket 刚建立连接的时候就可以主动发送消息给客户端了,然后就是在收到消息后返回一个消息给客户端.

3.过滤器

我们可以通过 WebSocketRouteraddFilterChain 方法为 WebSocketRouter 增加过滤器.下面例子中我们增加了一个 StringFilter过滤器,这是一个字符串过滤器是一个继承于WebSocketFilter接口的类,他的作用是将 WebSocket 接收的 ByteBuffer 转换成 一个字符串对象供 WebSocketRouter 的 onRecived 调用. 这样这个过滤器类就可以被多个场景复用,且保证了WebSocketRouter的可单元测试的特性。下面我们来看一下 StringFilter 的实现:

  1. public class StringFilter implements WebSocketFilter {
  2. @Override
  3. public Object encode(WebSocketSession session, Object object) {
  4. if(object instanceof String){
  5. String sourceString = TObject.cast(object);
  6. return ByteBuffer.wrap(sourceString.getBytes());
  7. }
  8. return object;
  9. }
  10. @Override
  11. public Object decode(WebSocketSession session,Object object) {
  12. if(object instanceof ByteBuffer){
  13. return TByteBuffer.toString((ByteBuffer)object);
  14. }
  15. return object;
  16. }
  17. }

由于只有一个过滤器,我们可以发现一个规律, 所有过滤器链的第一个位置过滤器的 decode 方法接收到的都是 ByteBuffer对象,所有过滤器链最后一个位置的过滤器的 encode 方法都返回都是 ByteBuffer 对象,这一点大家在开发的时候需要注意.

4.举个栗子

这里我们首先初始话一个HttpClient对象,接着我们通过webSocket方法来注册一个 WebSocket 消息处理类.最后通过实现WebSocketRouter类来处理 WebSocket 的消息.

  1. HttpClient httpClient = new HttpClient("ws://127.0.0.1:28080/","GBK2312",500);
  2. httpClient.webSocket("/websocket", new WebSocketRouter() {
  3. @Override
  4. public Object onOpen(WebSocketSession webSocketSession) {
  5. Logger.simple("WebSocket open");
  6. return "OPEN_MSG";
  7. }
  8. @Override
  9. public Object onRecived(WebSocketSession webSocketSession, Object message) {
  10. Logger.simple("Recive: "+message);
  11. try {
  12. return "RECIVE_MSG";
  13. }finally {
  14. webSocketSession.close();
  15. }
  16. }
  17. @Override
  18. public void onSent(WebSocketSession webSocketSession, Object message){
  19. Logger.simple("Send: " + message);
  20. }
  21. @Override
  22. public void onClose(WebSocketSession webSocketSession) {
  23. Logger.simple("WebSocket close");
  24. }
  25. }.addFilterChain(new StringFilter()));