通常,浏览器访问网页时,会向页面所在的服务器发送一个 HTTP 请求。Web 服务器确认请求并向浏览器发回响应。然而大多数情况下,当浏览器显示页面时实时信息已经过时了。幸运的是,随着 WebSocket 协议标准化,我们将向这一昔日窘况挥手告别。
新建连接:实例化一个 WebSocket 对象
本文主要讲述客户端编程中 WebSocket 的使用,所以不涉及服务器端配置及编码,我们就假设服务器端一切都配置好了。
为了建立一个到服务器端的连接,我们首先需要使用 WebSocket 构造函数实例化一个 WebSocket 对象:
|
|
WebSocket 构造函数第一个参数
WebSocket 构造函数可接受两个参数,其中,第一个参数必须是以 ws://
或 wss://
开头的完全限定的 URL,如果 URL 有语法错误,调用构造函数时将会抛出异常。该参数是必须的,不可省略。
这两种 URL 方案实际上是由 WebSocket 协议标准规定的,两者区别如下:
ws
:传输流量未经加密wss
:在ws
基础上使用传输层安全性 TLS(SSL)加密要传输的流量
两种 URL 方案的主要区别类似 HTTP 和 HTTPS,其中 wss
安全性更高,推荐使用,不过需要服务器端和客户端双方均支持。
WebSocket 构造函数第二个参数
WebSocket 构造函数接受的第二个参数,并非必须的,其主要用于客户端和服务器端间的协议协商。
协议协商对于确定 WebSocket 服务器支持的协议及版本很有用。当应用程序支持多个协议时,我们可以通过为 WebSocket 构造函数传入第二个参数,以使用协议协商选择与特定服务器通信的协议。
该参数类型有两种可能的类型:
- String 类型,值为客户端和服务器端均能理解的协议
- Arrary 类型,包含一组客户端支持的协议(String 类型)
|
|
WebSocket 事件处理
WebSocket 协议与 WebSocket API 均是事件驱动的,WebSocket 编程也遵循异步编程模式。只要 WebSocket 连接打开,应用程序就简单地监听事件。
要开始监听事件,只要为 WebSocket 事件添加回调函数即可。可以使用 addEventListener()
方法,也可以采用直接为 WebSocket 对象绑定事件处理函数的方式。
WebSocket 对象具有以下 4 个事件:
open 事件
一旦服务器响应了 WebSocket 连接请求,open
事件触并建立一个连接,open
事件对应的回调函数是 onopen()
。
|
|
到 open
事件触发时,服务器端与客户端之间的 WebSocket 协议握手已经完成,此时 WebSocket 已经准备好发送和接收数据。
message 事件
message
事件在接收到消息时触发,消息内容储存于事件对象 event
的 data
属性中,该事件回调函数是 onmessage()
。
|
|
除了普通文本,WebSocket 消息内容还可以是二进制数据,这种数据作为 Blob
消息或者 ArraryBuffer
消息处理。由于设置 WebSocket 消息二进制数据类型的应用程序会影响二进制消息,所以必须在读取数据之前决定用于客户端二进制数据的类型。
|
|
上面是 Blob 消息 message 事件处理程序示例代码,下面展示一下 ArraryBuffer 消息类型的处理过程:
|
|
error 事件
error
事件在响应意外故障时触发,与该事件对应的回调函数是 onerror()
。错误会导致 WebSocket 连接关闭。
close 事件
close
事件在 WebSocket 连接关闭时触发,对应的回调函数是 onclose()
。一旦连接关闭,客户端和服务器端之间不能再继续收发消息。
close
事件对象有 3 个有用的属性:
wasClean
:布尔值,表示连接是否顺利关闭。如果关闭连接是对来自服务器的一个 close 帧的响应,则该属性值为true
;如果是因为其他原因关闭连接,则该属性值为false
code
:服务器发送的关闭连接握手状态码reason
:服务器发送的关闭连接握手状态
WebSocket 方法
WebSocket API 为 WebSocket 对象提供了两个方法供我们调用。
send()
使用 send()
方法可以从客户端向服务器端发送消息。当 WebSocket 在客户端与服务器端之间建立了全双工双向连接之后,才可以在连接打开时调用 send()
方法。具体来说,我们应该在 open
事件触发之后,且在 close
事件触发之前调用 send()
发送消息。
|
|
除了普通文本消息,WebSocket API 还允许使用该方法发送二进制数据。
|
|
close()
通过使用 close()
方法,我们可以人为地手动关闭 WebSocket 连接或者终止连接尝试。如果连接已经关闭,那么该方法就什么都不做。
可以向 close()
方法传递两个可选参数:
code
:Number 类型,状态代码reason
:String 类型,文本字符串,传递一些关于关闭连接的信息
!!!注意: 这两个可选参数与 close
事件对象的属性值一致。
|
|
WebSocket 对象属性
WebSocket API 提供了多个开发者可以访问的 WebSocket 对象的属性,这些属性都从某一方面反映了 WebSocket 连接的信息。s
readyState
WebSocket 对象的 readyState
属性表示当前 WebSocket 连接状态,属性值与连接状态的对应关系如下表所示。
该属性是编程时最常使用的 WebSocket 对象属性,我们应该牢记其值所代表的 WebSocket 连接状态。
特性常量 | 取值 | 状态 |
---|---|---|
WebSocket.CONNECTING | 0 | 连接正在进行中,但还未建立 |
WebSocket.OPEN | 1 | 连接已经建立 |
WebSocket.CLOSEING | 2 | 连接正在进行关闭握手 |
WebSocket.CLOSED | 3 | 连接已经关闭 |
bufferedAmount
WebSocket 对象的 bufferedAmount
属性可以用检查已经进入发送队列,但是还未发送到服务器的字节数。
值得注意的是,这个属性报告的值不包括协议组帧开销或者操作系统、网络硬件所进行的缓冲。
protocol
WebSocket 对象的 protocol
属性值为 WebSocket 打开连接握手期间,服务器端所选择的协议名。
protocol
属性在最初的握手完成之前为空,如果服务器没有选择客户端提供的某个协议,则该属性保持空值。
开发工具推荐
- Chrome Developer Tools:监控网络流量,分析 HTTP 请求及响应头部
- Firefox Developer Tools:监控网络流量,分析 HTTP 请求及响应头部
- WireShark:抓取网络流量,详细分析网络协议帧、传送数据等
- websocket-monitor:强烈推荐!!!Firefox 大法好。这是一个 Firefox Developer Tools 扩展,可以方便地监控 WebSocket 流量。也可以直接在 Firefox Add-ons 下载:https://addons.mozilla.org/en-US/firefox/addon/websocket-monitor/