首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

反向 Ajax,第 3 部分 Web 服务器和 Socket.IO(4)

反向 Ajax,第 3 部分 Web 服务器和 Socket.IO(4)

抽象库考虑到所有主要的 API(Servlet 3.0 和 Jetty Continuation)、服务器端的所有本机支持以及在客户端实现 Reverse Ajax  的两种主要方法(Comet 和 WebSocket),编写您自己的 JavaScript 和 Java 代码以便将它们连接在一起会非常困难。您还必须考虑超时、连接故障、确认、排序和缓冲等因素。
本文的其余部分将向您介绍 Socket.IO。本  的第 4 部分将探讨 Atmosphere 和 CometD。这三个库均为开源库,它们都支持在许多服务器上使用 Comet 和 WebSocket。
Socket.IOSocket.IO 是一个 JavaScript 客户端库,可提供一个与 WebSocket 类似的 API,用该 API 连接到远程服务器,以便异步发送和接收消息。通过提供通用 API,Socket.IO 可支持多种传输:WebSocket、Flash Sockets、长轮询、流、forever Iframes 和 JSONP 轮询。Socket.IO 检测浏览器功能并尝试选择可用的最佳传输。Socket.IO 库几乎与所有的浏览器(包括旧版浏览器,如 IE 5.5)以及移动浏览器都兼容。它还提供了心跳、超时、断开连接和错误处理等功能。
Socket.IO 网站(参阅 )详细描述了库的工作原理以及使用哪种浏览器和 Reverse Ajax 技术。基本上,Socket.IO 使用一种可以使客户端库与服务器端的端点通信的通信协议,以便能够读懂 Socket.IO 协议。Socket.IO 最初是为 Node JS 开发的,它使用一个 JavaScript 引擎来构建快速服务器。许多项目都支持其他语言,其中包括 Java。
清单 4 显示了一个在客户端使用 Socket.IO JavaScript 库的示例。Socket.IO 网站中包含一些文档和示例。
清单 4. Socket.IO 客户端库的使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var socket = new io.Socket(document.domain, {
    resource: 'chat'
});
socket.on('connect', function() {
    // Socket.IO is connected
});
socket.on('disconnect', function(disconnectReason, errorMessage) {
    // Socket.IO disconnected
});
socket.on('message', function(mtype, data, error) {
    // The server sent an event
});

// Now that the handlers are defined, establish the connection:
socket.connect();




要使用 Socket.IO JavaScript 库,则需要一个称为 Socket.IO Java 的相应 Java 部件(参阅 )。该项目最初由 Apache Wave 团队创建,创建于推出 WebSocket 之前,可利用该项目为 Reverse Ajax 提供支持。Socket.IO Java 是 Ovea(一家专门从事事件驱动 Web 开发的公司)的分支,由 Ovea 维护,后来遭到遗弃。由于有多种传输方式,所以开发后端来支持 Socket.IO 客户端库非常复杂。本系列的第 4 部分将展示如何支持客户端库中的许多传输,这种支持并不是获得更好的可伸缩性和浏览器支持所必需的,因为有长轮询和 WebSocket 就已经足够。在 WebSocket 尚未发布的时候,Socket.IO 确实是一个不错的选择。
Socket.IO Java 使用 Jetty Continuation API 来挂起和重新开始使用请求。它使用本机 Jetty WebSockets API 来支持 WebSocket。您可以使用 Socket.IO Java 确定哪一个服务器将与 Web 应用程序协同工作。
下面的 清单 5 显示了一个如何在服务器上使用 Socket.IO 的示例。您必须定义一个扩展 SocketIOServlet 的 servlet ,并实现返回某种端点表示形式的方法。此 API 与 WebSocket API 非常相似。该 API 的优势在于它可在服务器端使用,独立于客户端所选择的传输方式。Socket.IO 将所有的传输类型转化为与服务器端的 API 相同。
清单 5. 聊天示例 servlet 中使用的 Socket.IO Java 库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public final class ChatServlet extends SocketIOServlet {
    private final BlockingQueue<Endpoint> endpoints =
        new LinkedBlockingQueue<Endpoint>();
  
    @Override
    protected SocketIOInbound doSocketIOConnect
                                        (HttpServletRequest request) {
        String user =
                (String) request.getSession().getAttribute("user");
        return user == null ? null : new Endpoint(this, user, request);
    }
  
    void broadcast(String data) {
        for (Endpoint endpoint : endpoints) {
            endpoint.send(data);
        }
    }
  
    void add(Endpoint endpoint) {
        endpoints.offer(endpoint);
    }
  
    void remove(Endpoint endpoint) {
        endpoints.remove(endpoint);
    }
}




清单 6 显示了如何返回端点。
清单 6. 在聊天示例 Endpoint 中使用的 Socket.IO Java 库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class Endpoint implements SocketIOInbound {
  
    [...]
  
    private SocketIOOutbound outbound;
  
    [...]

    @Override
    public void onConnect(SocketIOOutbound outbound) {
        this.outbound = outbound;
        servlet.add(this);
        servlet.broadcast(user + " connected");
    }
  
    @Override
    public void onDisconnect(DisconnectReason reason,
                             String errorMessage) {
        outbound = null;
        request.getSession().removeAttribute("user");
        servlet.remove(this);
        servlet.broadcast(user + " disconnected");
    }
  
    @Override
    public void onMessage(int messageType, String message) {
        if ("/disconnect".equals(message)) {
            outbound.close();
        } else {
            servlet.broadcast("[" + user + "] " + message);
        }
    }
  
    void send(String data) {
        try {
            if (outbound != null
    && outbound.getConnectionState() == ConnectionState.CONNECTED) {
                outbound.sendMessage(data);
            }
        } catch (IOException e) {
            outbound.close();
        }
    }
  
}




Socket.IO 的完整示例包含在 socketio 文件夹内的  中。
返回列表