HTML5 Web Sockets

最后更新:
阅读次数:

WebSocket 是一种在单个 TCP 连接上进行全双工通讯的协议。它的目标是在一个单独的持久连接上提供双向通信。

通信方式

  • 单工通信(Simplex Communication): 指消息只能单方向传输的工作方式
  • 半双工通信(Half-duplex Communication): 可以实现双向的通信,但不能在两个方向上同时进行,必须轮流交替地进行
  • 全双工通信(Full duplex Communication): 允许数据同时在两个方向上双向传输

由于 Web Sockets 使用了自定义协议,所以与普通的 URL 略有不同。未加密的连接不是 http://,而是 ws://;加密的连接也不是 https://,而是 wss://

使用自定义协议而不是 HTTP 协议的好处是:能够在客户端和服务器之间发送非常少量的数据,而不必担心 HTTP 那样字节级的开销。

  • Web Sockets 的优势
    • 较少的控制开销: 用于协议控制的数据包头部相对较小
    • 更强的实时性: 由于协议是全双工的,所以服务器可以随时主动给客户端下发数据
    • 保持连接状态: 一次建立,持久连接
    • 更好的二进制支持: Websocket 定义了二进制帧,相对 HTTP,可以更轻松地处理二进制内容
    • 可以支持扩展: Websocket 定义了扩展,用户可以扩展协议、实现部分自定义的子协议
    • 更好的压缩效果: 相对于 HTTP 压缩,Websocket 在适当的扩展支持下,可以沿用之前内容的上下文,在传递类似的数据时,可以显著地提高压缩率
  • 适用领域:聊天室、多人在线游戏或者端到端的在线协作工具等。

WebSocket 对象

WebSocket 对象提供了一组 API, 用于创建和管理 WebSocket 连接, 以及通过连接发送和接收数据。

  • new WebSocket(url , protocols)

    • url: 表示响应 WebSocket 的地址
    • protocols: 可以是一个单个的协议名字字符串或者包含多个协议名字字符串的数组。这些字符串用来表示子协议,这样做可以让一个服务器实现多种 WebSocket 子协议
  • 以下是一些常量,用来描述 WebSocket 连接的状态

    • WebSocket.CONNECTING: 0,表示正在连接中
    • WebSocket.OPEN:1,表示连接已完成并准备好进行通信
    • WebSocket.CLOSING:2,表示连接正在关闭中
    • WebSocket.CLOSED:3,表示连接已经关闭
  • WebSocket 对象的属性

    • binaryType: 表示被传输二进制的内容的类型。取值应当是 blobarraybuffer
    • bufferedAmount: 表示调用 send() 方法加入到队列中等待传输但是还没有发出的字节数。该值会在所有队列数据被发送后重置为 0
    • extensions: 表示服务器选定的扩展。目前这个属性只是一个空字符串,或者是一个包含所有扩展的列表
    • protocol: 表示服务器选定的子协议名字的字符串。这个属性的取值为构造器传入的 protocols 参数
    • readyState: 表示当前连接的状态
    • url: 表示传入构造器的 URL
  • WebSocket 对象的方法

    • void send(data): 通过 WebSocket 连接向服务器发送数据
    • void close(code , reason):
      • code: 一个数字值表示关闭连接的状态号,参看 CloseEvent.code
      • reason: 一个可读的字符串,表示连接被关闭的原因
  • WebSocket 对象中的事件

    • open: 当 readyState 的值变为 OPEN 的时候会触发该事件
    • message: 当有消息到达的时候触发该事件
    • close: 当 WebSocket 对象的 readyState 状态变为 CLOSED 时会触发该事件
    • error: 当有错误发生时触发该事件

实例解析

  • 注意:同源策略对 Web Sockets 不再适用,因此通过 Web Sockets 可以打开到任何站点的连接,至于是否会与某个域中的页面通信,则完全取决于服务器。

在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

为了创建 Websocket 连接,需要通过浏览器发出请求,之后服务器进行回应,这个过程通常称为“握手”(handshaking)。

为了进行 Web Sockets 数据传送测试,我这里使用了别人用 Nodejs 搭建的一个支持 Web Sockets 的服务器:ws: a Node.js WebSocket library

  • 在你测试的地方新建个文件夹:websocket-test
  • 假设你已经安装好了 nodejs,然后在 cmd 命令行找到上面文件夹的地址
  • 安装 ws:npm install ws
  • 在这个文件夹下新建文件 server.js
// server.js
const WebSocket = require("ws");
const WebSocketServer = WebSocket.Server;
const server = new WebSocketServer({ port: 8075 });

server.on("connection", function(socket) {
// 收到客户端消息后,马上回复
socket.on("message", function(message) {
console.log(message);
if (message === "close connection") {
socket.close();
} else {
socket.send("客户端弟弟,消息收到了~");
}
});

// 关闭连接时,显示下面的消息
socket.on("close", function() {
console.log("服务器:Connection closed~");
});
});
  • 在 nodejs 下运行这个文件:node server.js
  • 现在支持 WebSocket 的本地服务器已经启动,准备进行测试
  • 编写好以下的测试代码,在浏览器控制端运行
// 新建一个 WebSocket 对象,并进行初始化
// 我们在服务器设置的端口为 8075
var socket = new WebSocket("ws://localhost:8075", "protocol1");

// web socket 连接建立后,立即向服务器发送一条消息
socket.onopen = function() {
socket.send("服务器哥哥,收到请回复~");
};

// 接受服务器响应的消息
socket.onmessage = function(event) {
console.log(event.data);
};

// 关闭连接时显示下面的消息
socket.onclose = function() {
console.log("客户端:Connection closed~");
};
  • 运行之后即可看到互相通信成功
  • 然后再在浏览器控制端数一下面的某一段代码,即可终止与服务器的连接
// 方法一,客户端发送表示终止连接的消息给服务器,服务器终止与客户端的连接
socket.send("close connection");

// 方法二,客户端直接终止与服务器的连接
socket.close();
  • 终止连接后,即可看到终止的消息
  • 更改文件 server.js 内容如下
const WebSocket = require("ws");
const WebSocketServer = WebSocket.Server;
const server = new WebSocketServer({ port: 8075 });

server.on("connection", function(socket) {
// 收到客户端消息后,马上回复
socket.on("message", function(message) {
console.log(message);
if (message === "close connection") {
socket.close();
} else if (message === "broadcast") {
// 给当前与服务器有连接的所有客户端发送消息
server.clients.forEach(function each(client) {
if (client !== server && client.readyState === WebSocket.OPEN) {
client.send("这是一条群发消息~");
}
});
} else {
socket.send("客户端弟弟,消息收到了~");
}
});

// 关闭连接时,显示下面的消息
socket.on("close", function() {
console.log("服务器:Connection closed~");
});
});
  • 接下来体验下 WebSocket 群发功能
  • 打开多个页面,分别在浏览器控制端输入并运行上面的测试代码
  • 然后选一个页面,控制端输入 socket.send(‘broadcast’);
  • 运行即可在其他与服务器有连接的页面看到服务器群发的消息

好了,Web Sockets 就侃这么多了。 *_*