您的网站已准备好使用 WebSockets






4.86/5 (4投票s)
本教程提供了对 W3C WebSocket API 及其底层 WebSocket 协议的简单介绍。
WebSockets 已经稳定,随时可供开发者开始创建创新的应用程序和服务。本教程提供了对 W3C WebSocket API 及其底层 WebSocket 协议的简单介绍。更新的 Flipbook 演示使用了最新版本的 API 和协议。
工作组已取得重大进展,WebSocket API 已成为 W3C 候选推荐。Internet Explorer 10 实现的是此版本的规范。您可以在此处了解该规范的演变。
WebSockets 使 Web 应用程序能够在浏览器中提供实时通知和更新。开发者在处理浏览器最初的 HTTP 请求-响应模型限制时遇到了问题,该模型并非为实时场景而设计。WebSockets 使浏览器能够与服务建立双向、全双工的通信通道。双方都可以使用此通道立即向另一方发送数据。现在,从社交网络和游戏到金融网站,各种网站都可以提供更好的实时场景,理想情况下,可以在不同浏览器中使用相同的标记。
使用回显示例介绍 WebSocket API
下面的代码片段使用 ASP.NET 的 System.Web.WebSockets 命名空间创建的简单回显服务器,以回显从应用程序发送的文本和二进制消息。该应用程序允许用户输入文本发送并作为文本消息回显,或绘制图片作为二进制消息发送并回显。
有关允许您试验 WebSocket 和 HTTP 轮询之间延迟和性能差异的更复杂示例,请参阅 Flipbook 演示。
连接到 WebSocket 服务器的详细信息
这个简单的解释基于应用程序和服务器之间的直接连接。如果配置了代理,则 IE10 会通过向代理发送 HTTP CONNECT 请求来启动该过程。
创建 WebSocket 对象时,客户端和服务器之间会进行握手以建立 WebSocket 连接。
IE10 通过向服务器发送 HTTP 请求来启动此过程
GET /echo HTTP/1.1 Host: example.microsoft.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Origin: http://microsoft.com Sec-WebSocket-Version: 13
让我们看一下此请求的每个部分。
连接过程以标准的 HTTP GET 请求开始,该请求允许请求穿过防火墙、代理和其他中间件。
GET /echo HTTP/1.1 Host: example.microsoft.com
HTTP Upgrade 标头请求服务器将应用程序层协议从 HTTP 切换到 WebSocket 协议。
Upgrade: websocket Connection: Upgrade
服务器会转换其响应中 Sec-WebSocket-Key 标头的值,以表明它理解 WebSocket 协议。
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin 标头由 IE10 设置,以允许服务器强制执行基于源的安全策略。
Sec-WebSocket-Version: 13
Sec-WebSocket-Version 标头标识了请求的协议版本。版本 13 是 IETF 提议标准中的最终版本。
Sec-WebSocket-Version: 13
如果服务器接受升级应用程序层协议的请求,它将返回一个 HTTP 101 Switching Protocols 响应。
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade
为了证明其理解 WebSocket 协议,服务器会对其从客户端请求中收到的 Sec-WebSocket-Key 执行标准化的转换,并在 Sec-WebSocket-Accept 标头中返回结果。
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
然后,IE10 将比较 Sec-WebSocket-Key 和 Sec-WebSocket-Accept,以验证服务器是 WebSocket 服务器,而不是一个自命不凡的 HTTP 服务器。
客户端握手在 IE10 和服务器之间建立了基于 TCP 的 HTTP 连接。在服务器返回其 101 响应后,应用程序层协议将从 HTTP 切换到 WebSocket,后者使用之前建立的 TCP 连接。
此时 HTTP 完全被排除在外。使用轻量级的 WebSocket 线协议,现在任何一方都可以随时发送或接收消息。
编程连接到 WebSocket 服务器
WebSocket 协议定义了 两个新的 URI 方案,它们类似于 HTTP 方案。
- "ws:" "//" host [ ":" port ] path [ "?" query ] 模仿 "http:" 方案。其默认端口为 80。它用于不安全(未加密)的连接。
- "wss:" "//" host [ ":" port ] path [ "?" query ] 模仿 "https:" 方案。其默认端口为 443。它用于通过 传输层安全隧道传输的安全连接。
当存在代理或网络中间件时,安全连接成功的可能性会更高,因为中间件不太愿意尝试转换安全流量。
以下代码片段建立了一个 WebSocket 连接
var host = "ws://example.microsoft.com"; var socket = new WebSocket(host);
ReadyState – 准备… 就绪… 开始…!
WebSocket.readyState 属性表示连接的状态:CONNECTING、OPEN、CLOSING 或 CLOSED。当 WebSocket 首次创建时,readyState 设置为 CONNECTING。当连接建立时,readyState 设置为 OPEN。如果连接未能建立,则 readyState 设置为 CLOSED。
注册 Open 事件
要接收连接已创建的通知,应用程序必须注册 open 事件。
socket.onopen = function (openEvent) {
document.getElementById("serverStatus").innerHTML = 'Web Socket State::' + 'OPEN';
};,
发送和接收消息的详细信息
在成功握手后,应用程序和 WebSocket 服务器可以交换 WebSocket 消息。消息由一个或多个消息片段或数据“帧”组成。
每个帧包含的信息,例如:
- 帧长度
- 消息的第一帧中的消息类型(二进制或文本)
- 一个标志 (FIN),指示这是否是消息的最后一帧
IE10 在将帧传递给脚本之前,会将其重新组装成一条完整的消息。
编程发送和接收消息
send API 允许应用程序将消息作为 UTF-8 文本、ArrayBuffers 或 Blobs 发送到 WebSocket 服务器。
例如,此代码片段检索用户输入的文本,并将其作为 UTF-8 文本消息发送到服务器以进行回显。它验证 WebSocket 是否处于 OPEN 状态。
function sendTextMessage() {
if (socket.readyState != WebSocket.OPEN)
return;
var e = document.getElementById("textmessage");
socket.send(e.value);
}
此代码片段检索用户在画布上绘制的图像,并将其作为二进制消息发送到服务器。
function sendBinaryMessage() {
if (socket.readyState != WebSocket.OPEN)
return;
var sourceCanvas = document.getElementById('source');
// msToBlob returns a blob object from a canvas image or drawing
socket.send(sourceCanvas.msToBlob());
// ...
}
注册 Message 事件
要接收消息,应用程序必须注册 message 事件。事件处理程序会收到一个 MessageEvent,其中包含 MessageEvent.data 中的数据。数据可以作为文本或二进制消息接收。
当收到二进制消息时,WebSocket.binaryType 属性控制是将消息数据作为 Blob 还是 ArrayBuffer 数据类型返回。该属性可以设置为“blob”或“arraybuffer”。
下面的示例使用默认值,即“blob”。
此代码片段接收来自 websocket 服务器的回显图像或文本。如果数据是 Blob,则返回的是图像并绘制在目标画布上;否则,返回的是 UTF-8 文本消息并显示在文本字段中。
socket.onmessage = function (messageEvent) {
if (messageEvent.data instanceof Blob) {
var destinationCanvas = document.getElementById('destination');
var destinationContext = destinationCanvas.getContext('2d');
var image = new Image();
image.onload = function () {
destinationContext.clearRect(0, 0, destinationCanvas.width, destinationCanvas.height);
destinationContext.drawImage(image, 0, 0);
}
image.src = URL.createObjectURL(messageEvent.data);
} else {
document.getElementById("textresponse").value = messageEvent.data;
}
};
关闭 WebSocket 连接的详细信息
与打开握手类似,也存在关闭握手。任一端(应用程序或服务器)都可以发起此握手。
一种特殊类型的帧——关闭帧——会发送到另一端。关闭帧可能包含可选的状态代码和关闭原因。协议定义了一组适当的 状态代码值。关闭帧的发送者在发送关闭帧后不得发送其他应用程序数据。
当另一端收到关闭帧时,它会用自己的关闭帧进行响应。它可以在响应关闭帧之前发送挂起的消息。
编程关闭 WebSocket 并注册 Close 事件
应用程序使用 close API 在打开的连接上发起关闭握手。
socket.close(1000, "normal close");
要接收连接已关闭的通知,应用程序必须注册 close 事件。
socket.onclose = function (closeEvent) {
document.getElementById("serverStatus").innerHTML = 'Web Socket State::' + 'CLOSED';
};
close API 接受两个可选参数:由协议定义的 status code 和 description。status code 必须是 1000 或 3000 到 4999 之间的值。执行 close 时,readyState 属性设置为 CLOSING。在 IE10 收到服务器的关闭响应后,readyState 属性设置为 CLOSED,并触发 close 事件。
使用 Fiddler 查看 WebSockets 流量
Fiddler 是一个流行的 HTTP 调试代理。最新版本对 WebSocket 协议提供了一些支持。您可以检查 WebSocket 握手中交换的标头。
所有 WebSocket 消息也会被记录下来。在下面的屏幕截图中,您可以看到“spiral”作为 UTF-8 文本消息发送到服务器并被回显。
结论
如果您想了解更多关于 WebSockets 的信息,可以观看 2011 年 9 月 Microsoft //Build/ 会议的这些环节:
如果您想了解如何使用 Microsoft 技术创建 WebSocket 服务,这些帖子是不错的入门资料:
立即开始使用 WebSockets 进行开发!