📅  最后修改于: 2020-10-17 05:57:21             🧑  作者: Mango
Web很大程度上是围绕HTTP的请求/响应范例构建的。客户端加载网页,然后在用户单击下一页之前,没有任何反应。在2005年左右,AJAX开始使网络更具活力。尽管如此,所有HTTP通信仍由客户端控制,这需要用户交互或定期轮询才能从服务器加载新数据。
使服务器能够在知道新数据可用的那一刻将数据发送到客户端的技术已经存在了很长时间。它们以“ Push”或“ Comet”之类的名称命名。
使用长轮询时,客户端将打开与服务器的HTTP连接,这将使其保持打开状态,直到发送响应为止。只要服务器实际有新数据,它就会发送响应。长轮询和其他技术效果很好。但是,所有这些共享一个问题,它们带来了HTTP的开销,这并不适合用于低延迟的应用程序。例如,浏览器中的多人射击游戏或任何其他具有实时组件的在线游戏。
Web套接字规范定义了一个API,用于在Web浏览器和服务器之间建立“套接字”连接。用外行术语来说,客户端和服务器之间存在持久连接,并且双方都可以随时开始发送数据。
Web套接字连接可以使用构造函数简单地打开-
var connection = new WebSocket('ws://html5rocks.websocket.org/echo', ['soap', 'xmpp']);
ws是WebSocket连接的新URL架构。也有WSS,对于安全WebSocket连接相同的方式HTTPS用于安全的HTTP连接。
立即将一些事件处理程序附加到连接上,可以让您知道何时打开连接,收到传入消息或出现错误。
第二个参数接受可选的子协议。它可以是一个字符串或字符串的数组。每个字符串应代表一个子协议名称,并且服务器仅接受数组中传递的子协议之一。可以通过访问WebSocket对象的协议属性来确定接受的子协议。
// When the connection is open, send some data to the server
connection.onopen = function () {
connection.send('Ping'); // Send the message 'Ping' to the server
};
// Log errors
connection.onerror = function (error) {
console.log('WebSocket Error ' + error);
};
// Log messages from the server
connection.onmessage = function (e) {
console.log('Server: ' + e.data);
};
一旦与服务器建立连接(当打开事件被触发时),我们就可以使用连接对象上的send(您的消息)方法开始向服务器发送数据。它过去仅支持字符串,但在最新规范中,它现在也可以发送二进制消息。要发送二进制数据,请使用Blob或ArrayBuffer对象。
// Sending String
connection.send('your message');
// Sending canvas ImageData as ArrayBuffer
var img = canvas_context.getImageData(0, 0, 400, 320);
var binary = new Uint8Array(img.data.length);
for (var i = 0; i < img.data.length; i++) {
binary[i] = img.data[i];
}
connection.send(binary.buffer);
// Sending file as Blob
var file = document.querySelector('input[type = "file"]').files[0];
connection.send(file);
同样,服务器可以随时向我们发送消息。每当这种情况发生时,都会触发onmessage回调。回调接收一个事件对象,并且可以通过data
属性访问实际消息。
WebSocket还可以接收最新规范中的二进制消息。二进制帧可以Blob或ArrayBuffer格式接收。要指定接收到的二进制文件的格式,请将WebSocket对象的binaryType属性设置为’blob’或’arraybuffer’。默认格式为“ blob”。
// Setting binaryType to accept received binary as either 'blob' or 'arraybuffer'
connection.binaryType = 'arraybuffer';
connection.onmessage = function(e) {
console.log(e.data.byteLength); // ArrayBuffer object if binary
};
WebSocket的另一个新增功能是扩展。使用扩展名,可以发送经过压缩,复用等的帧。
// Determining accepted extensions
console.log(connection.extensions);
作为一种现代协议,跨域通信直接嵌入到WebSocket中。 WebSocket启用任何域上的各方之间的通信。服务器决定是使其服务对所有客户端还是仅对驻留在一组定义良好的域上的客户端可用。
每一项新技术都会带来一系列新问题。对于WebSocket,它是与代理服务器的兼容性的代理,它在大多数公司网络中中介HTTP连接。 WebSocket协议使用HTTP升级系统(通常用于HTTP / SSL)将HTTP连接“升级”到WebSocket连接。某些代理服务器不喜欢这样,将断开连接。因此,即使给定的客户端使用WebSocket协议,也可能无法建立连接。这使得下一节更加重要:)
使用WebSocket为服务器端应用程序创建了全新的使用模式。虽然传统的服务器堆栈(例如LAMP)是围绕HTTP请求/响应周期设计的,但它们通常无法很好地处理大量开放的WebSocket连接。同时保持大量连接打开需要一种以低性能成本获得高并发性的体系结构。