WebSocket的URL都是以“ws”为前两个字符,它代表所使用的是WebSocket协议,而其余部分与HTTP协议中的URL相同,包括主机、端口、路径以及查询字符串。如果需要使用安全连接,可以在协议名称上加一个额外的“s”字符。
可以指定的消息处理函数共有四种:onopen、onmessage、onclose和onerror。在传递消息时需要调用send方法,而在关闭连接时则需要调用close方法。由于不存在类似于connect这样的方法,因此客户端必须监听onopen消息,以确认连接已建立,随后才能够进行send操作。另一种选择是对WebSocket对象的readyState属性进行轮询,但这种方式并不推荐使用。显然,在onmessage处理函数中总是能够调用send操作的。send操作由客户端异步执行,这也意味着JavaScript在将消息传递给接收者的过程中无须等待其结果,而是直接返回。文本消息或二进制消息在接收时不存在任何差别,因此在onmessage处理函数中必须对事件的data参数进行检查。WebSocket提供了一些属性,可用于获取状态、判断二进制消息的格式等目的。而其它浏览器厂商的特定实现中还可以包含更多的属性,因此请记得仔细阅读浏览器的文档,以了解详细的信息。
Java 端的 WebSocket 实现Java中的JSR 356定义了常见的(客户端)与服务端的Java WebSocket通信API。在Java的实现中会指定终结点与服务端终结点对象,这与JavaScript中的WebSocket实现颇为类似。可以通过注解的方式将某个Java类指定为一个终结点对象,而通过OnOpen、OnMessage、OnError和 OnClose等注解信息指定事件处理函数。在每种类型的处理函数中,都可以将重要的Session对象作为一个传入参数。Session对象让开发者能够访问发送消息的功能,并且能够保持与WebSocket连接相关的状态特性。消息的发送可以使用同步或异步机制,并且在两种类型的发送机制中都可以指定超时时间。通过指定相应的解码器,二进制与文本数据都能够自动转换为任意的Java对象,而编码器则允许WebSocket发送任意类型的Java对象。对于某个特定的WebSocket URL路径,消息处理函数只能对应文本消息类型或二进制消息类型的其中一种。Java中未提供消息链的功能,但也可以通过编程的方式对其进行组织。 Java端的API很容易上手,它提供了一种可自定义的配置对象,能够影响最初的握手过程,决定所支持的子协议、版本,并且提供访问重要的servlet 对象API的功能。终结点不仅能够通过注解的方式进行部署,也能够通过编程的方式所生成。
对 Web 应用的重新思考WebSocket对于以下类型的应用程序的开发是一种非常自然的选择:
其实,WebSocket在传统的Web应用中也能够展现其优势。大多数Web应用都是基于请求 - 响应这一范式进行设计的。虽然AJAX能够实现异步操作,但在继续处理下一步操作之间,仍然必须等待响应返回。而由于WebSocket连接只需建立一次,从而避免了为每次数据交换重建连接的过程,并且在后续的通信中也无需发送多余的HTTP头信息。这种优势在SSL类型的连接上体现得尤为明显,因为最初的连接握手是一个开销很大的操作。浏览器端的WebSocket发送操作是完全异步的,而Java的服务端代码在发送消息后无需进行等待。由于发送消息的这种自由度,在应用中或许需要对某些操作进行手动记录,以保持应用状态的一致性。在使用WebSocket时也能够模拟请求 - 响应这一范式,但如此一来,WebSocket作为一种真正的异步双向消息传递系统的优势也被大大消减了。由于以上所描述的这些特性,因此应当鼓励开发者在某些场景中对应用程序的设计方式进行重新思考。
假设某一个应用程序包含了复杂的用户界面,其中某些区域的功能需要通过服务端的大量计算才能够生成对应的内容。传统的基于AJAX的实现方式可以选择一种延迟调用的机制,通过某个内容请求调用以生成这一区域的内容。而在使用WebSocket的场合下,服务端可以在浏览器做好准备的情况下直接发送内容,而无需对某个AJAX请求进行响应。AJAX请求这一方式的缺陷在于,由于浏览器所发送的请求是串行的,因此服务端的处理过程无法针对请求的顺序进行相应的优化。而WebSocket为服务端提供了一个自行决定最佳的内容生成方式的机会,因而能够提升Web应用的整体响应性。
要用效地利用WebSocket的功能,还需要仔细考虑几个额外的要点。由于在WebSocket中随时可能出现网络连接的丢失,使数据无法正确地传递,因此对于一些至关重要的数据需要进行一些额外的手动记录操作。一般来说,所收到的每条消息都必须提供足够的信息,以指示如何对其进行处理。但没有有效的手段能够了解信息的请求者是谁,是来自客户端的请求,还是说服务端想要更新某些内容。在具体使用WebSocket的过程中,可能需要对 Web应用的设计进行更深入的重新思考。此外,JavaScript代码的功能可以迁移至服务端,打个比方,用户的输入可以立即发送给服务端进行处理,通过这种方式能够实现一些复杂的数据校验操作,而这些校验功能或许是JavaScript所无法处理的。用户的输入还能够即时地保存在后台系统中,因此浏览器就无需将最终的数据传递给服务器进行额外的数据校验,因为数据在保存在后台期间已经经过了校验。如果要使某个应用从富Web客户端转为一种轻量级的客户端,就可以考虑以这种方式增加服务端代码的职责。
使用WebSocket时所需注意的要点