Skip to content

计算机网络之 WebSocket #27

Open
@myLightLin

Description

@myLightLin

什么是 WebSocket

WebSocket 是一个双向、全双工的即时通信协议,它与 HTTP 协议一样基于 TCP,在客户端和服务器之间建立连接。WebSocket 是有状态的,这意味着一旦建立连接,就能一直保持连接打开,类似 Keep Alive 的能力,直到其中一方主动关闭断开连接。

那为什么需要 WebSocket 呢?这就要从 HTTP 说起,很早以前网络传输都是使用的 http,这是典型的 客户端-服务器 模式。客户端发起一个 http 请求,服务器响应资源,随后连接被关闭。这是一个单向的过程,而且控制权在 客户端 这边。通常是由客户端去发起请求,然后服务端作应答。那有没办法让服务端也可以向客户端发送消息呢?实际上 HTTP2 已经支持 Server Push 的功能,但这只是服务端去主动发送附带资源给客户端,客户端并没有一个明确的事件可以监听到服务端发来的数据。所以想实现真正的双向通信,还需要有专门的机制才行。于是 HTML5 新增了 WebSocket 协议,它支持双向、全双工通信,客户端和服务端都可以收发消息,而且是实时通信,端到端接收。

如何建立 WebSocket 连接

客户端和服务器需要进行 握手,通常是客户端先发送一个 http 请求,在请求头有个 Upgrade 字段, 表示希望升级成 WebSocket 连接。请求示例如下:

GET ws://websocket.example.com/ HTTP/1.1
Origin: http://example.com
Connection: Upgrade
Host: websocket.example.com
Upgrade: websocket

服务端如果同意,就会响应 101 状态码,告诉客户端说可以切换使用 WebSocket 协议,响应 payload 示例如下:

HTTP/1.1 101 Switching Protocols
Date: Wed, 25 Oct 2017 10:07:34 GMT
Connection: Upgrade
Upgrade: WebSocket

当连接建立的时候,就会触发 open 事件,可以通过监听该事件来执行操作:

var socket = new WebSocket('ws://websocket.example.com');

socket.onopen = function(event) {
  console.log('WebSocket is connected.')
}

这时 socket 连接已经建立完毕,接下来客户端和服务端都可以发送消息了,可以通过 send 方法来发送消息,通过监听 message 事件来接收消息。对于错误处理,可以监听 error 事件来处理。对于关闭连接,通过监听 close 事件。

socket.onmessage = function(event) {
  console.log('接收的数据:', event.data)
}

socket.onclose = function(reasonCode, description) {
  console.log('close: ', reasonCode, description)
}

socket.onerror = function() {
  console.log('error')
}

WebSocket 的心跳机制

心跳机制 是指连接建立后,客户端和服务端两方都可以通过发送 ping 报文,然后另一方接收到后,必须回复一个 pong 报文。这样做的目的是为了探测其中一方是否还处于连接状态。由于 WebSocket 是双向传输,任意一方都可以发送消息及断开连接,如果出现一些意外情况比如网络错误导致其中一方断开了,那如何让另一方发现呢?这就要有一个探测机制,来实时检查对方的连接状态,避免无谓等待所带来的花销。所以心跳机制就是让双方都确认对方的在线状态。

WebSocket 的应用场景

  • 实时网络通信应用程序,比如 QQ 聊天,对话框里互相发送消息,群发消息就是使用的 WebSocket
  • 游戏 APP:平时我们玩的游戏,对实时性要求非常高,因为数据不断地被服务器接受处理,但是我们看屏幕 UI 是自动刷新的,这就使用了 WebSocket 技术

WebSocket 与 HTTP 的区别

  • HTTP 是单向通信,比如客户端发送,服务端响应;而 WebSocket 是双向通信,实时收发消息
  • HTTP 是无状态的,协议以 http(s):// 开头,而 WebSocket 是有状态的,以 ws(s):// 开头
  • WebSocket 是长连接的,除非一方主动关闭否则一直保持连接;而 HTTP 连接数据传输完就会被关闭
  • WebSocket 传输数据比 HTTP 连接快

image

即时通信的其它解决方案

除了 WebSocket 外,以下技术也可以实现即时通信:

  • 短轮询:前端每隔一段时间发起 ajax 请求,获取服务器更新内容
  • 长轮询:是对 短轮询 的改进,客户端发起请求到服务器后,一直保持打开状态,等服务器有内容更新就响应一次数据。
  • SSE:Server Sent Event,基于流的服务端推送技术。它允许服务端异步的向客户端推送数据,它有点类似 发布-订阅 模式,服务端可以决定向客户端发送哪些数据,客户端可以通过一套 API 来订阅内容的获取。
  • Socket.IO: 基于 WebSocket 做了一些兼容性工作,封装了一些更好用的接口。

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions