# Web 的交互过程
Web 应用典型的信息交互过程通常是:客户端通过浏览器发出一个请求,服务端接收请求后进行处理并返回结果给客户端,然后客户端浏览器将信息呈现出来。
这种机制对于信息交互不是特别频繁的应用尚能相安无事,但是对于那些实时要求比较高的应用来说(比如在线游戏),当客户端浏览器准备呈现获取到的信息的时候,这些信息在服务器端可能已经过时,所以,保持客户端和服务器端的信息同步是实时 Web 应用的关键要素。 在 WebSocket 规范出来之前,开发人员想实现这种应用,不得不采用一些折中的方案,其中最常用的就是轮询(Polling)和 Comet(轮询的改进版本,又可细分为长轮询机制与流技术)技术。这几种方案基本都是在用 Ajax 来模拟实时的效果,服务器与客户端编程都比较复杂,而且效率不高。
# Web 消息推送的技术
轮询(polling):Ajax 隔一段时间就去服务器查询是否有改变,从而进行增量式的更新。但是间隔多长时间去查询成了问题,因为性能和即时性造成了严重的反比关系。间隔太短,连续不断的请求会冲垮服务器,间隔太长,务器上的新数据就需要越多的时间才能到达客户机。
- 优点:服务端逻辑简单;
- 缺点:其中大多数请求可能是无效请求,在大量用户轮询很频繁的情况下对服务器的压力很大;
- 应用:并发用户量少,而且要求消息的实时性不高,一般很少采用;
长轮询(long-polling):客户端向服务器发送 Ajax 请求,服务器接到请求后 hold 住连接,直到有新消息或超时(设置)才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。
- 优点:实时性高,无消息的情况下不会进行频繁的请求;
- 缺点:服务器维持着连接期间会消耗资源;
基于 iframe 及 htmlfile 的流(streaming)方式:iframe 流方式是在页面中插入一个隐藏的 iframe,利用其 src 属性在服务器和客户端之间创建一条长链接,服务器向 iframe 传输数据(通常是 HTML,内有负责插入信息的 javascript),来实时更新页面。
- 优点:消息能够实时到达;
- 缺点:服务器维持着长连接期会消耗资源;
插件提供 socket 方式:比如利用 Flash XMLSocket,Java Applet 套接口,Activex 包装的 socket。
- 优点:原生 socket 的支持,和 PC 端和移动端的实现方式相似;
- 缺点:浏览器端需要装相应的插件;
WebSocket:是 HTML5 开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。
- 优点:更好的节省服务器资源和带宽并达到实时通讯;
- 缺点:目前还未普及,浏览器支持不好;
HTML5 WebSocket 设计出来的目的就是要取代轮询和 Comet 技术,使客户端浏览器具备像 C/S 架构下桌面系统的实时通讯能力。浏览器向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。因为 WebSocket 连接本质上就是一个 TCP 连接,所以在数据传输的稳定性和数据传输量的大小方面,和轮询以及 Comet 技术比较,具有很大的性能优势。
# WebSocket 协议
WebSocket 协议本质上是一个基于 TCP 协议。为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息 ”Upgrade: WebSocket” 表明这是一个申请协议升级的 HTTP 请求(详细的 WebSocket 消息的内容这里就不详细说了,基本和 HTTP 的差不多,而且都是由 WebSocket 对象自动发送和接收的,对用户透明),服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。
WebSocket API 最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻,相互推送信息。WebSocket 并不限于以 Ajax (或 XmlHttpRequest)方式通信,因为 Ajax 技术需要客户端发起请求,而 WebSocket 服务器和客户端可以彼此相互推送信息;XmlHttpRequest 通信受到域的限制,而 WebSocket 允许跨域通信。
需要注意的问题是,除了安全和性能以外,服务端只管往 socket 里面写数据就可以了,WebSocket 的通信数据全部是以 ”\x00″ 开头以 ”\xFF” 结尾的,无论是服务端发出的数据还是客户端发送的数据都遵从这个格式,唯一不同的是客户端的 WebSocket 对象能够自动将头尾去除,获得主体数据,这就省却了在客户端处理原始数据的必要,而且 WebSocket 通信的消息总是 UTF-8 格式的。